优化代码

super_signature
nineven 5 years ago
parent a4e9579236
commit ff81f62d95
  1. 15
      fir_client/src/App.vue
  2. 9
      fir_client/src/assets/icon/iconfont.css
  3. 41
      fir_client/src/assets/icon/iconfont.svg
  4. 10
      fir_client/src/components/FirAppInfosBase.vue
  5. 8
      fir_client/src/components/FirAppInfosbaseinfo.vue
  6. 7
      fir_client/src/components/FirAppInfosdevices.vue
  7. 7
      fir_client/src/components/FirAppInfossecurity.vue
  8. 15
      fir_client/src/components/FirApps.vue
  9. 36
      fir_client/src/components/FirDownload.vue
  10. 8
      fir_client/src/components/FirHeader.vue
  11. 189
      fir_client/src/components/FirSuperSignBase.vue
  12. 12
      fir_client/src/components/FirUserProfileBase.vue
  13. 6
      fir_client/src/components/FirUserProfileChangePwd.vue
  14. 7
      fir_client/src/components/FirUserProfileInfo.vue
  15. 20
      fir_client/src/components/FirUserProfileStorage.vue
  16. 1
      fir_client/src/main.js
  17. 61
      fir_client/src/restful/index.js
  18. 8
      fir_client/src/utils/index.js
  19. 2
      fir_ser/api/admin.py
  20. 97
      fir_ser/api/migrations/0001_initial.py
  21. 1
      fir_ser/api/migrations/0002_auto_20200503_1120.py
  22. 8
      fir_ser/api/migrations/0003_apptodeveloper.py
  23. 1
      fir_ser/api/migrations/0004_auto_20200504_2054.py
  24. 1
      fir_ser/api/migrations/0005_apptodeveloper_release_file.py
  25. 5
      fir_ser/api/migrations/0006_udidsyncdeveloper.py
  26. 1
      fir_ser/api/urls.py
  27. 6
      fir_ser/api/utils/TokenManager.py
  28. 1
      fir_ser/api/utils/ali/__init__.py
  29. 1
      fir_ser/api/utils/ali/api.py
  30. 1
      fir_ser/api/utils/ali/client/__init__.py
  31. 1
      fir_ser/api/utils/ali/client/api/__init__.py
  32. 1
      fir_ser/api/utils/ali/client/basic.py
  33. 1
      fir_ser/api/utils/ali/pay/__init__.py
  34. 1
      fir_ser/api/utils/ali/pay/api/base.py
  35. 1
      fir_ser/api/utils/ali/yun/api/base.py
  36. 1
      fir_ser/api/utils/ali/yun/api/sms.py
  37. 1
      fir_ser/api/utils/ali/yun/api/vod.py
  38. 2
      fir_ser/api/utils/ali/yun/basic.py
  39. 8
      fir_ser/api/utils/app/apputils.py
  40. 4
      fir_ser/api/utils/app/dadf.py
  41. 8
      fir_ser/api/utils/app/firApi.py
  42. 10
      fir_ser/api/utils/app/iossignapi.py
  43. 7
      fir_ser/api/utils/app/randomstrings.py
  44. 3
      fir_ser/api/utils/app/raqc.py
  45. 26
      fir_ser/api/utils/app/shellcmds.py
  46. 50
      fir_ser/api/utils/app/supersignutils.py
  47. 5
      fir_ser/api/utils/auth.py
  48. 3
      fir_ser/api/utils/captcha_verify.py
  49. 3
      fir_ser/api/utils/crontab/sync_cache.py
  50. 4
      fir_ser/api/utils/middlewares.py
  51. 4
      fir_ser/api/utils/permission.py
  52. 6
      fir_ser/api/utils/response.py
  53. 19
      fir_ser/api/utils/serializer.py
  54. 3
      fir_ser/api/utils/storage/aliyunApi.py
  55. 30
      fir_ser/api/utils/storage/caches.py
  56. 2
      fir_ser/api/utils/storage/localApi.py
  57. 2
      fir_ser/api/utils/storage/qiniuApi.py
  58. 5
      fir_ser/api/utils/utils.py
  59. 2
      fir_ser/api/views/apps.py
  60. 23
      fir_ser/api/views/download.py
  61. 5
      fir_ser/api/views/login.py
  62. 6
      fir_ser/api/views/receiveudids.py
  63. 36
      fir_ser/api/views/supersign.py
  64. 11
      fir_ser/api/views/uploads.py
  65. 20
      fir_ser/fir_ser/settings.py
  66. 1
      fir_ser/fir_ser/urls.py
  67. 8
      fir_ser/tests/postudid.py

@ -9,8 +9,7 @@
export default {
name: 'app',
data() {
return {
}
return {}
},
}
</script>
@ -20,13 +19,12 @@
background-color: rgba(0, 166, 224, 0.18)
}
@font-face {font-family: "iconfont";
@font-face {
font-family: "iconfont";
src: url('./assets/icon/iconfont.eot?t=1583637102320'); /* IE9 */
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
src: url('./assets/icon/iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('./assets/icon/iconfont.woff?t=1583637102320') format('woff'),
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */
url('./assets/icon/iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('./assets/icon/iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
@ -74,7 +72,4 @@
}
</style>

@ -1,10 +1,9 @@
@font-face {font-family: "iconfont";
@font-face {
font-family: "iconfont";
src: url('iconfont.eot?t=1583637102320'); /* IE9 */
src: url('iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
src: url('iconfont.eot?t=1583637102320#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1583637102320') format('woff'),
url('iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */
url('iconfont.ttf?t=1583637102320') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('iconfont.svg?t=1583637102320#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {

@ -20,34 +20,51 @@ Created by iconfont
/>
<missing-glyph/>
<glyph glyph-name="android" unicode="&#58909;" d="M269.401218 547.905l484.587674 0 0-11.106965c0-120.589472 0.023536-241.183038-0.011256-361.76944-0.011256-40.771589-21.756513-62.327534-62.705134-62.342884-10.184967 0-20.37198 0-29.858028 0 0-43.198871 0.467651-85.178985-0.171915-127.141702-0.397043-26.024723-22.889313-47.623647-48.671513-48.568159-27.686573-1.013073-52.970422 18.175965-53.951773 44.760436-1.579985 42.982954-0.425695 86.064145-0.425695 130.026402l-92.891643 0c0-17.075911 0.033769-34.169217-0.005117-51.256384-0.055259-25.179472 0.483001-50.374294-0.428765-75.523067-0.896416-24.611537-20.249183-44.734854-44.115754-47.749514-25.325805-3.202948-49.012274 11.464099-56.531528 35.426861-1.660826 5.300726-2.638083 11.033287-2.675946 16.571421-0.234337 35.778878-0.174985 71.555709-0.064468 107.33561 0.013303 4.910846 0.836041 9.815553 1.417279 16.121166-12.051477 0-23.86657-0.073678-35.68678 0.011256-34.978652 0.254803-57.743122 22.928199-57.767682 58.021461-0.100284 122.571616-0.039909 245.152443-0.042979 367.729176L269.400195 547.905 269.401218 547.905zM754.197646 583.671599 268.922311 583.671599c4.508687 83.888596 52.172243 136.038326 123.015731 173.068707-7.217379 10.940167-14.230096 21.587668-21.263279 32.217772-5.119601 7.730055-10.30674 15.407921-15.398712 23.150256-3.591805 5.460362-9.344832 11.614525-1.36509 17.062608 8.616238 5.885034 12.135388-2.347464 15.941064-7.959276 9.094122-13.428847 18.064424-26.946722 27.064402-40.440038 11.086499-16.617469 11.078313-16.613376 30.132274-11.05887 60.601216 17.662265 120.804367 16.659425 180.590008-3.89061 2.139733-0.738827 4.331655-1.331321 7.135514-2.183735 12.395308 18.558681 24.680099 36.96182 36.96489 55.358819 1.471514 2.206248 2.910283 4.427846 4.428869 6.598278 3.459798 4.948709 7.856945 7.618515 13.384845 3.53757 5.008061-3.693112 4.154623-8.404414 0.994654-13.125949-10.67513-15.95232-21.285792-31.954783-31.911804-47.940872-2.371-3.571339-4.705162-7.167237-7.42204-11.304464 70.458725-36.700877 118.544907-88.950891 122.990149-173.090197L754.197646 583.671599zM641.381208 678.031687c0.150426 14.033621-11.603269 25.974581-25.713638 26.131147-14.242376 0.159636-25.844621-11.30651-25.957185-25.65224-0.116657-14.520715 11.002588-25.810852 25.501814-25.904996C629.645932 652.518616 641.236921 663.776008 641.381208 678.031687L641.381208 678.031687zM433.369663 678.65488c-0.187265 14.328333-11.883655 25.780153-26.066679 25.512047-14.080693-0.260943-25.824155-12.32777-25.576515-26.275433 0.251733-14.231119 11.936867-25.453718 26.327622-25.300222C422.521594 652.744767 433.556928 664.105512 433.369663 678.65488L433.369663 678.65488zM892.258025 385.416256c-0.004093-36.07359 0.095167-72.149227-0.028653-108.219747-0.11154-31.752168-21.937638-54.680367-51.753711-54.658877-29.79049 0.017396-51.8059 23.100114-51.836599 54.654784-0.067538 73.140811-0.149403 146.276505 0.061398 219.415268 0.075725 26.923186 19.805068 48.538483 45.833885 51.248198 27.095102 2.819209 50.834782-13.987572 56.574506-40.425711 1.105171-5.102205 1.090844-10.510378 1.105171-15.782451 0.089028-35.413558 0.045025-70.821999 0.040932-106.234533L892.258025 385.416256zM234.306932 385.412163c0-37.7293 0.35918-75.465762-0.132006-113.184829-0.302899-23.12672-16.584724-42.608423-38.748513-48.26526-21.668509-5.526877-45.432749 3.454682-56.523341 23.153326-4.52199 8.035-7.7935 17.987676-7.869225 27.101241-0.624217 74.130348-0.546446 148.266835-0.252757 222.399229 0.116657 29.218462 23.174815 51.633984 51.857065 51.633984 28.801976-0.004093 51.323922-22.078855 51.64831-51.639101 0.414439-37.065174 0.102331-74.132394 0.102331-111.199615-0.028653 0-0.055259 0-0.084934 0L234.306932 385.411139zM234.306932 385.412163" horiz-adv-x="1024" />
<glyph glyph-name="android" unicode="&#58909;"
d="M269.401218 547.905l484.587674 0 0-11.106965c0-120.589472 0.023536-241.183038-0.011256-361.76944-0.011256-40.771589-21.756513-62.327534-62.705134-62.342884-10.184967 0-20.37198 0-29.858028 0 0-43.198871 0.467651-85.178985-0.171915-127.141702-0.397043-26.024723-22.889313-47.623647-48.671513-48.568159-27.686573-1.013073-52.970422 18.175965-53.951773 44.760436-1.579985 42.982954-0.425695 86.064145-0.425695 130.026402l-92.891643 0c0-17.075911 0.033769-34.169217-0.005117-51.256384-0.055259-25.179472 0.483001-50.374294-0.428765-75.523067-0.896416-24.611537-20.249183-44.734854-44.115754-47.749514-25.325805-3.202948-49.012274 11.464099-56.531528 35.426861-1.660826 5.300726-2.638083 11.033287-2.675946 16.571421-0.234337 35.778878-0.174985 71.555709-0.064468 107.33561 0.013303 4.910846 0.836041 9.815553 1.417279 16.121166-12.051477 0-23.86657-0.073678-35.68678 0.011256-34.978652 0.254803-57.743122 22.928199-57.767682 58.021461-0.100284 122.571616-0.039909 245.152443-0.042979 367.729176L269.400195 547.905 269.401218 547.905zM754.197646 583.671599 268.922311 583.671599c4.508687 83.888596 52.172243 136.038326 123.015731 173.068707-7.217379 10.940167-14.230096 21.587668-21.263279 32.217772-5.119601 7.730055-10.30674 15.407921-15.398712 23.150256-3.591805 5.460362-9.344832 11.614525-1.36509 17.062608 8.616238 5.885034 12.135388-2.347464 15.941064-7.959276 9.094122-13.428847 18.064424-26.946722 27.064402-40.440038 11.086499-16.617469 11.078313-16.613376 30.132274-11.05887 60.601216 17.662265 120.804367 16.659425 180.590008-3.89061 2.139733-0.738827 4.331655-1.331321 7.135514-2.183735 12.395308 18.558681 24.680099 36.96182 36.96489 55.358819 1.471514 2.206248 2.910283 4.427846 4.428869 6.598278 3.459798 4.948709 7.856945 7.618515 13.384845 3.53757 5.008061-3.693112 4.154623-8.404414 0.994654-13.125949-10.67513-15.95232-21.285792-31.954783-31.911804-47.940872-2.371-3.571339-4.705162-7.167237-7.42204-11.304464 70.458725-36.700877 118.544907-88.950891 122.990149-173.090197L754.197646 583.671599zM641.381208 678.031687c0.150426 14.033621-11.603269 25.974581-25.713638 26.131147-14.242376 0.159636-25.844621-11.30651-25.957185-25.65224-0.116657-14.520715 11.002588-25.810852 25.501814-25.904996C629.645932 652.518616 641.236921 663.776008 641.381208 678.031687L641.381208 678.031687zM433.369663 678.65488c-0.187265 14.328333-11.883655 25.780153-26.066679 25.512047-14.080693-0.260943-25.824155-12.32777-25.576515-26.275433 0.251733-14.231119 11.936867-25.453718 26.327622-25.300222C422.521594 652.744767 433.556928 664.105512 433.369663 678.65488L433.369663 678.65488zM892.258025 385.416256c-0.004093-36.07359 0.095167-72.149227-0.028653-108.219747-0.11154-31.752168-21.937638-54.680367-51.753711-54.658877-29.79049 0.017396-51.8059 23.100114-51.836599 54.654784-0.067538 73.140811-0.149403 146.276505 0.061398 219.415268 0.075725 26.923186 19.805068 48.538483 45.833885 51.248198 27.095102 2.819209 50.834782-13.987572 56.574506-40.425711 1.105171-5.102205 1.090844-10.510378 1.105171-15.782451 0.089028-35.413558 0.045025-70.821999 0.040932-106.234533L892.258025 385.416256zM234.306932 385.412163c0-37.7293 0.35918-75.465762-0.132006-113.184829-0.302899-23.12672-16.584724-42.608423-38.748513-48.26526-21.668509-5.526877-45.432749 3.454682-56.523341 23.153326-4.52199 8.035-7.7935 17.987676-7.869225 27.101241-0.624217 74.130348-0.546446 148.266835-0.252757 222.399229 0.116657 29.218462 23.174815 51.633984 51.857065 51.633984 28.801976-0.004093 51.323922-22.078855 51.64831-51.639101 0.414439-37.065174 0.102331-74.132394 0.102331-111.199615-0.028653 0-0.055259 0-0.084934 0L234.306932 385.411139zM234.306932 385.412163"
horiz-adv-x="1024"/>
<glyph glyph-name="android1" unicode="&#58902;" d="M391.428571 620q9.142857 0 15.714286 6.571429T413.714286 642.285714t-6.571429 15.714286T391.428571 664.571429t-15.428571-6.571429-6.285714-15.714286 6.285714-15.714285 15.428571-6.571429z m241.142858 0q9.142857 0 15.428571 6.571429t6.285714 15.714285-6.285714 15.714286-15.428571 6.571429-15.714286-6.571429T610.285714 642.285714t6.571429-15.714285T632.571429 620zM168.571429 514.857143q24 0 41.142857-17.142857t17.142857-41.142857v-245.714286q0-24.571429-16.857143-41.714286t-41.428571-17.142857-41.714286 17.142857-17.142857 41.714286V456.571429q0 24 17.142857 41.142857t41.714286 17.142857z m605.714285-10.857143v-380.571429q0-26.285714-18.285714-44.571428t-44-18.285714h-42.857143v-129.714286q0-24.571429-17.142857-41.714286t-41.714286-17.142857-41.714285 17.142857-17.142858 41.714286v129.714286H472.571429v-129.714286q0-24.571429-17.142858-41.714286t-41.714285-17.142857q-24 0-41.142857 17.142857t-17.142858 41.714286l-0.571428 129.714286h-42.285714q-26.285714 0-44.571429 18.285714t-18.285714 44.571428V504h524.571428zM641.714286 735.428571q61.142857-31.428571 97.714285-87.714285t36.571429-123.142857H247.428571q0 66.857143 36.571429 123.142857T382.285714 735.428571l-40.571428 74.857143q-4 7.428571 2.857143 11.428572 7.428571 3.428571 11.428571-3.428572l41.142857-75.428571q54.285714 24 114.857143 24t114.857143-24l41.142857 75.428571q4 6.857143 11.428571 3.428572 6.857143-4 2.857143-11.428572z m272.571428-278.857142v-245.714286q0-24.571429-17.142857-41.714286t-41.714286-17.142857q-24 0-41.142857 17.142857t-17.142857 41.714286V456.571429q0 24.571429 17.142857 41.428571t41.142857 16.857143q24.571429 0 41.714286-16.857143t17.142857-41.428571z" horiz-adv-x="1024" />
<glyph glyph-name="android1" unicode="&#58902;"
d="M391.428571 620q9.142857 0 15.714286 6.571429T413.714286 642.285714t-6.571429 15.714286T391.428571 664.571429t-15.428571-6.571429-6.285714-15.714286 6.285714-15.714285 15.428571-6.571429z m241.142858 0q9.142857 0 15.428571 6.571429t6.285714 15.714285-6.285714 15.714286-15.428571 6.571429-15.714286-6.571429T610.285714 642.285714t6.571429-15.714285T632.571429 620zM168.571429 514.857143q24 0 41.142857-17.142857t17.142857-41.142857v-245.714286q0-24.571429-16.857143-41.714286t-41.428571-17.142857-41.714286 17.142857-17.142857 41.714286V456.571429q0 24 17.142857 41.142857t41.714286 17.142857z m605.714285-10.857143v-380.571429q0-26.285714-18.285714-44.571428t-44-18.285714h-42.857143v-129.714286q0-24.571429-17.142857-41.714286t-41.714286-17.142857-41.714285 17.142857-17.142858 41.714286v129.714286H472.571429v-129.714286q0-24.571429-17.142858-41.714286t-41.714285-17.142857q-24 0-41.142857 17.142857t-17.142858 41.714286l-0.571428 129.714286h-42.285714q-26.285714 0-44.571429 18.285714t-18.285714 44.571428V504h524.571428zM641.714286 735.428571q61.142857-31.428571 97.714285-87.714285t36.571429-123.142857H247.428571q0 66.857143 36.571429 123.142857T382.285714 735.428571l-40.571428 74.857143q-4 7.428571 2.857143 11.428572 7.428571 3.428571 11.428571-3.428572l41.142857-75.428571q54.285714 24 114.857143 24t114.857143-24l41.142857 75.428571q4 6.857143 11.428571 3.428572 6.857143-4 2.857143-11.428572z m272.571428-278.857142v-245.714286q0-24.571429-17.142857-41.714286t-41.714286-17.142857q-24 0-41.142857 17.142857t-17.142857 41.714286V456.571429q0 24.571429 17.142857 41.428571t41.142857 16.857143q24.571429 0 41.714286-16.857143t17.142857-41.428571z"
horiz-adv-x="1024"/>
<glyph glyph-name="android2" unicode="&#58922;" d="M256 128c0-25.6 17.066667-42.666667 42.666667-42.666667h42.666666v-149.333333c0-34.133333 29.866667-64 64-64s64 29.866667 64 64V85.333333h85.333334v-149.333333c0-34.133333 29.866667-64 64-64s64 29.866667 64 64V85.333333h42.666666c25.6 0 42.666667 17.066667 42.666667 42.666667V554.666667H256v-426.666667zM149.333333 554.666667C115.2 554.666667 85.333333 524.8 85.333333 490.666667v-298.666667c0-34.133333 29.866667-64 64-64S213.333333 157.866667 213.333333 192v298.666667C213.333333 524.8 183.466667 554.666667 149.333333 554.666667z m725.333334 0c-34.133333 0-64-29.866667-64-64v-298.666667c0-34.133333 29.866667-64 64-64s64 29.866667 64 64v298.666667c0 34.133333-29.866667 64-64 64z m-213.333334 247.466666L716.8 857.6c8.533333 8.533333 8.533333 21.333333 0 29.866667-8.533333 8.533333-21.333333 8.533333-29.866667 0l-64-64C593.066667 844.8 554.666667 853.333333 512 853.333333s-81.066667-8.533333-115.2-25.6L337.066667 891.733333c-8.533333 4.266667-25.6 4.266667-34.133334 0-4.266667-8.533333-4.266667-25.6 0-34.133333l55.466667-55.466667C298.666667 755.2 256 682.666667 256 597.333333h512c0 85.333333-42.666667 162.133333-106.666667 204.8zM426.666667 682.666667H384V725.333333h42.666667v-42.666666z m213.333333 0h-42.666667V725.333333h42.666667v-42.666666z" horiz-adv-x="1024" />
<glyph glyph-name="android2" unicode="&#58922;"
d="M256 128c0-25.6 17.066667-42.666667 42.666667-42.666667h42.666666v-149.333333c0-34.133333 29.866667-64 64-64s64 29.866667 64 64V85.333333h85.333334v-149.333333c0-34.133333 29.866667-64 64-64s64 29.866667 64 64V85.333333h42.666666c25.6 0 42.666667 17.066667 42.666667 42.666667V554.666667H256v-426.666667zM149.333333 554.666667C115.2 554.666667 85.333333 524.8 85.333333 490.666667v-298.666667c0-34.133333 29.866667-64 64-64S213.333333 157.866667 213.333333 192v298.666667C213.333333 524.8 183.466667 554.666667 149.333333 554.666667z m725.333334 0c-34.133333 0-64-29.866667-64-64v-298.666667c0-34.133333 29.866667-64 64-64s64 29.866667 64 64v298.666667c0 34.133333-29.866667 64-64 64z m-213.333334 247.466666L716.8 857.6c8.533333 8.533333 8.533333 21.333333 0 29.866667-8.533333 8.533333-21.333333 8.533333-29.866667 0l-64-64C593.066667 844.8 554.666667 853.333333 512 853.333333s-81.066667-8.533333-115.2-25.6L337.066667 891.733333c-8.533333 4.266667-25.6 4.266667-34.133334 0-4.266667-8.533333-4.266667-25.6 0-34.133333l55.466667-55.466667C298.666667 755.2 256 682.666667 256 597.333333h512c0 85.333333-42.666667 162.133333-106.666667 204.8zM426.666667 682.666667H384V725.333333h42.666667v-42.666666z m213.333333 0h-42.666667V725.333333h42.666667v-42.666666z"
horiz-adv-x="1024"/>
<glyph glyph-name="ios" unicode="&#58892;" d="M521.996 659.402c13.596 0.316 26.587 2.344 38.944 5.874l1.477-1.023c25.485 8.525 47.394 21.707 65.751 38.675l-25.33-22.506c28.822 15.94 52.712 37.447 70.922 63.249l-36.429-39.535c28.139 24 50.335 54.116 64.645 88.349l-34.464-58.168c22.406 27.513 39.057 60.636 47.571 96.894l-25.474-60.785c14.141 25.287 23.872 54.935 27.305 86.475l-11.137-47.132c6.314 18.235 10.235 39.273 10.832 61.141-0.92-14.951-0.492-7.646-0.492-0.24 0 7.406-0.428 14.711-1.261 21.894-114.436-13.762-202.632-110.063-202.632-226.963 0-1.99 0.026-3.974 0.076-5.952zM813.027 279.983c-9.291 23.371-14.678 50.452-14.678 78.791 0 2.616 0.046 5.222 0.137 7.816 0.877 22.699 5.309 44.464 12.755 64.776 8.765 26.429 27.096 55.391 50.856 78.871 1.828 9.48 42.301 41.542 89.752 59.323-84.33 32.038-144.712 69.372-214.043 76.759 0.404 0.843-15.633 2.529-32.046 2.637l-53.878-0.333-15.629-4.312-11.857-3.773-15.091-5.389-10.779-8.623-17.785-7.006-14.552-5.928-10.24-3.773-12.396-3.773h-7.006c-2.507-0.304-5.41-0.478-8.354-0.478s-5.847 0.174-8.699 0.511c-2.079-0.302-4.891-0.455-7.739-0.455-2.848 0-5.659 0.153-8.427 0.452l-5.585-0.030-11.857 3.234-8.623 3.234-12.396 3.234-20.48 8.084-8.084 2.695-14.552 5.389-9.701 3.234-13.474 4.312h-10.24l-14.013 2.695h-10.779l-12.935 3.773c-35.215-0.199-68.68-7.463-99.123-20.442-100.455-45.409-170.936-147.27-170.936-265.593 0-6.498 0.213-12.947 0.631-19.339l-0.046-53.025c0-4.312 0-19.402 3.773-29.103s0-10.779 3.234-16.168 3.234-17.246 5.389-25.869 3.234-11.318 4.851-16.707 4.312-16.168 7.006-24.253 4.312-11.857 6.467-17.785l8.084-22.636 7.545-17.246c3.234-7.006 5.928-14.552 9.162-21.558l8.084-16.168 10.779-21.019 9.162-15.629 11.318-19.402 21.558-32.337 10.24-13.474 12.396-15.629 10.779-12.396 12.396-13.474 11.318-10.779 12.396-11.318 11.318-8.623 12.396-9.162 11.318-6.467 11.857-6.467 10.779-3.773 11.857-3.773 14.013-4.312h12.396c17.291 0.666 33.606 3.944 48.855 9.45 35.686 19.327 84.485 32.203 136.187 33.26-11.243-0.381-6.541-0.215-1.8-0.215 4.741 0 9.443-0.166 14.101-0.492l7.996 0.035 14.552-3.234 9.162-2.695 11.318-3.773 9.701-3.773 14.013-5.928 12.396-5.389 8.084-2.695 10.779-3.773h45.811c39.742 3.516 74.688 21.631 99.914 48.874 71.609 68.094 126.848 162.124 151.674 267.874-5.067-48.749 17.64 18.78 26.966 90.511-106.339-115.262-156.75-58.206-177.238 11.642z" horiz-adv-x="1024" />
<glyph glyph-name="ios" unicode="&#58892;"
d="M521.996 659.402c13.596 0.316 26.587 2.344 38.944 5.874l1.477-1.023c25.485 8.525 47.394 21.707 65.751 38.675l-25.33-22.506c28.822 15.94 52.712 37.447 70.922 63.249l-36.429-39.535c28.139 24 50.335 54.116 64.645 88.349l-34.464-58.168c22.406 27.513 39.057 60.636 47.571 96.894l-25.474-60.785c14.141 25.287 23.872 54.935 27.305 86.475l-11.137-47.132c6.314 18.235 10.235 39.273 10.832 61.141-0.92-14.951-0.492-7.646-0.492-0.24 0 7.406-0.428 14.711-1.261 21.894-114.436-13.762-202.632-110.063-202.632-226.963 0-1.99 0.026-3.974 0.076-5.952zM813.027 279.983c-9.291 23.371-14.678 50.452-14.678 78.791 0 2.616 0.046 5.222 0.137 7.816 0.877 22.699 5.309 44.464 12.755 64.776 8.765 26.429 27.096 55.391 50.856 78.871 1.828 9.48 42.301 41.542 89.752 59.323-84.33 32.038-144.712 69.372-214.043 76.759 0.404 0.843-15.633 2.529-32.046 2.637l-53.878-0.333-15.629-4.312-11.857-3.773-15.091-5.389-10.779-8.623-17.785-7.006-14.552-5.928-10.24-3.773-12.396-3.773h-7.006c-2.507-0.304-5.41-0.478-8.354-0.478s-5.847 0.174-8.699 0.511c-2.079-0.302-4.891-0.455-7.739-0.455-2.848 0-5.659 0.153-8.427 0.452l-5.585-0.030-11.857 3.234-8.623 3.234-12.396 3.234-20.48 8.084-8.084 2.695-14.552 5.389-9.701 3.234-13.474 4.312h-10.24l-14.013 2.695h-10.779l-12.935 3.773c-35.215-0.199-68.68-7.463-99.123-20.442-100.455-45.409-170.936-147.27-170.936-265.593 0-6.498 0.213-12.947 0.631-19.339l-0.046-53.025c0-4.312 0-19.402 3.773-29.103s0-10.779 3.234-16.168 3.234-17.246 5.389-25.869 3.234-11.318 4.851-16.707 4.312-16.168 7.006-24.253 4.312-11.857 6.467-17.785l8.084-22.636 7.545-17.246c3.234-7.006 5.928-14.552 9.162-21.558l8.084-16.168 10.779-21.019 9.162-15.629 11.318-19.402 21.558-32.337 10.24-13.474 12.396-15.629 10.779-12.396 12.396-13.474 11.318-10.779 12.396-11.318 11.318-8.623 12.396-9.162 11.318-6.467 11.857-6.467 10.779-3.773 11.857-3.773 14.013-4.312h12.396c17.291 0.666 33.606 3.944 48.855 9.45 35.686 19.327 84.485 32.203 136.187 33.26-11.243-0.381-6.541-0.215-1.8-0.215 4.741 0 9.443-0.166 14.101-0.492l7.996 0.035 14.552-3.234 9.162-2.695 11.318-3.773 9.701-3.773 14.013-5.928 12.396-5.389 8.084-2.695 10.779-3.773h45.811c39.742 3.516 74.688 21.631 99.914 48.874 71.609 68.094 126.848 162.124 151.674 267.874-5.067-48.749 17.64 18.78 26.966 90.511-106.339-115.262-156.75-58.206-177.238 11.642z"
horiz-adv-x="1024"/>
<glyph glyph-name="IOS" unicode="&#59020;" d="M737.007 358.636c-1.092 104.007 84.833 153.888 88.595 156.316-48.181 70.512-123.305 80.221-150.126 81.435-63.958 6.432-124.761-37.622-157.165-37.622-32.404 0-82.405 36.652-135.441 35.681-69.663-1.092-133.863-40.535-169.787-102.915-72.453-125.732-18.569-311.903 52.065-413.727 34.467-49.881 75.609-105.828 129.616-103.887 51.943 2.063 71.604 33.618 134.47 33.618s80.464-33.618 135.563-32.646c55.948 1.092 91.387 50.851 125.611 100.852 39.564 57.89 55.948 113.959 56.798 116.63-1.214 0.729-109.105 41.991-110.197 166.267zM633.605 663.742c28.641 34.71 47.938 83.012 42.72 131.072-41.264-1.699-91.265-27.428-120.878-62.138-26.457-30.826-49.881-79.978-43.569-127.067 45.997-3.641 93.085 23.423 121.727 58.132z" horiz-adv-x="1024" />
<glyph glyph-name="IOS" unicode="&#59020;"
d="M737.007 358.636c-1.092 104.007 84.833 153.888 88.595 156.316-48.181 70.512-123.305 80.221-150.126 81.435-63.958 6.432-124.761-37.622-157.165-37.622-32.404 0-82.405 36.652-135.441 35.681-69.663-1.092-133.863-40.535-169.787-102.915-72.453-125.732-18.569-311.903 52.065-413.727 34.467-49.881 75.609-105.828 129.616-103.887 51.943 2.063 71.604 33.618 134.47 33.618s80.464-33.618 135.563-32.646c55.948 1.092 91.387 50.851 125.611 100.852 39.564 57.89 55.948 113.959 56.798 116.63-1.214 0.729-109.105 41.991-110.197 166.267zM633.605 663.742c28.641 34.71 47.938 83.012 42.72 131.072-41.264-1.699-91.265-27.428-120.878-62.138-26.457-30.826-49.881-79.978-43.569-127.067 45.997-3.641 93.085 23.423 121.727 58.132z"
horiz-adv-x="1024"/>
<glyph glyph-name="ios1" unicode="&#58881;" d="M615.913 712.238c31.803 40.968 55.898 98.81 47.218 157.832-52.08-3.61-112.838-36.802-148.25-79.991-32.36-39.164-58.954-97.353-48.607-153.876 56.94-1.805 115.545 32.15 149.639 76.035zM896.859 156.8c-22.776-50.481-33.677-73.117-62.98-117.835-40.97-62.496-98.603-140.266-170.055-140.822-63.467-0.694-79.854 41.386-165.957 40.9s-104.156-41.733-167.693-41.107c-71.451 0.695-126.03 70.827-166.929 133.32-114.364 174.568-126.376 379.48-55.897 488.498 50.203 77.354 129.294 122.558 203.661 122.558 75.688 0 123.253-41.593 185.956-41.593 60.758 0 97.768 41.663 185.26 41.663 66.245 0 136.447-36.109 186.441-98.603-163.805-89.922-137.278-324.275 28.192-387.047v0.068h0.001z" horiz-adv-x="1024" />
<glyph glyph-name="ios1" unicode="&#58881;"
d="M615.913 712.238c31.803 40.968 55.898 98.81 47.218 157.832-52.08-3.61-112.838-36.802-148.25-79.991-32.36-39.164-58.954-97.353-48.607-153.876 56.94-1.805 115.545 32.15 149.639 76.035zM896.859 156.8c-22.776-50.481-33.677-73.117-62.98-117.835-40.97-62.496-98.603-140.266-170.055-140.822-63.467-0.694-79.854 41.386-165.957 40.9s-104.156-41.733-167.693-41.107c-71.451 0.695-126.03 70.827-166.929 133.32-114.364 174.568-126.376 379.48-55.897 488.498 50.203 77.354 129.294 122.558 203.661 122.558 75.688 0 123.253-41.593 185.956-41.593 60.758 0 97.768 41.663 185.26 41.663 66.245 0 136.447-36.109 186.441-98.603-163.805-89.922-137.278-324.275 28.192-387.047v0.068h0.001z"
horiz-adv-x="1024"/>
<glyph glyph-name="ios2" unicode="&#58955;" d="M812.2 345.2c-7.2 96.1 56.4 156.8 116.4 199-56.4 50.6-105.4 99.5-209.1 104.5-83.6 3.4-121.8-43.8-200-45.5-72.7-1.7-67.3 52.3-218.2 37.1C170.5 626.8 55.9 505.4 65 335.1c9.1-183.8 147.3-438.3 276.3-438.3 90.9 1.7 112.7 42.1 187.3 42.1 92.7 0 114.5-50.6 187.3-40.5C841.4-84.7 959.5 99 959.5 158c-69.1 33.8-138.2 91.1-147.3 187.2z m-105.4 526C534.1 849.3 485 702.6 494.1 635.2c132.7-6.7 232.7 123.1 212.7 236z" horiz-adv-x="1024" />
<glyph glyph-name="ios2" unicode="&#58955;"
d="M812.2 345.2c-7.2 96.1 56.4 156.8 116.4 199-56.4 50.6-105.4 99.5-209.1 104.5-83.6 3.4-121.8-43.8-200-45.5-72.7-1.7-67.3 52.3-218.2 37.1C170.5 626.8 55.9 505.4 65 335.1c9.1-183.8 147.3-438.3 276.3-438.3 90.9 1.7 112.7 42.1 187.3 42.1 92.7 0 114.5-50.6 187.3-40.5C841.4-84.7 959.5 99 959.5 158c-69.1 33.8-138.2 91.1-147.3 187.2z m-105.4 526C534.1 849.3 485 702.6 494.1 635.2c132.7-6.7 232.7 123.1 212.7 236z"
horiz-adv-x="1024"/>
<glyph glyph-name="Android" unicode="&#59092;" d="M512 192.7c-41.8 0-75.6 34-75.6 75.6V499.7c0 41.6 33.8 75.6 75.6 75.6 20.2 0 39.1-7.8 53.5-22.1 14.3-14.3 22.1-33.3 22.1-53.5v-231.5c0-20.2-7.8-39.1-22.1-53.5-14.4-14-33.3-22-53.5-22M243.1 400c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.4 30.6 0 55.2 24.8 55.2 55.4V344.9c0 30.3-24.8 55.1-55.2 55.1m593-11.4H297.3V409c0 83.4 45.5 160.9 119.9 206.9l-28.9 52.5c-3.6 6.1-4.4 14.1-2.4 21.2 2.2 7.1 7.1 13.4 13.6 16.8 4.1 2.4 8.8 3.6 13.4 3.6 10.2 0 19.7-5.6 24.6-14.6l30.4-55.2c31.4 11.4 64.4 17.3 98.7 17.3 34.8 0 68.1-5.8 99.4-17.5l30.1 55.4c4.9 9 14.3 14.6 24.6 14.6 4.6 0 9.2-1.2 13.4-3.4 6.8-3.6 11.7-9.7 13.6-17 2.2-7.3 1.2-14.8-2.4-21.4l-28.9-52.8c74.4-46 119.9-123.5 119.9-206.9v-19.9h-0.2zM633.8 442.7l38.7 70.5c1.9 3.6 0.7 8.5-2.9 10.5-3.9 1.9-8.5 0.7-10.5-3.2l-38.9-71.2c-32.8 14.6-69.5 22.9-108.2 22.6-38.7 0-75.4-8-107.9-22.6l-38.9 71c-1.9 3.6-6.8 5.1-10.5 3.2s-5.1-6.8-3.2-10.5l38.7-70.5C314.3 403.4 263 329 263 243.4h498c-0.3 85.8-51.3 160.2-127.2 199.3M398.5 333.8c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9s-9.3-20.9-20.9-20.9m226.8 0c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9s-9.5-20.9-20.9-20.9M419.3 66c-41.6 0-75.6 33.8-75.6 75.6V243.7h-19.9c-21.2 0-41.1 8.3-56.2 23.1-15.1 15.1-23.3 34.8-23.1 56.2V702h535.1v-379c0-43.8-35.5-79.3-79.3-79.3h-19.9v-102.1c0-41.6-33.8-75.6-75.6-75.6-20.2 0-39.1 7.8-53.5 22.1-14.3 14.3-22.1 33.3-22.1 53.5V243.7h-34v-102.1c-0.3-41.6-34.4-75.6-75.9-75.6M189 307.7c0-32.6 26.3-59.1 59.1-59.1h40.1V126c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.4V248.8h74.6v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V248.8H624c32.6 0 59.1 26.5 59.1 59.1V666.8H188.8l0.2-359.1z m570.6 6.8c-41.6 0-75.6 33.8-75.6 75.6V621.5c0 41.8 33.8 75.6 75.6 75.6s75.6-33.8 75.6-75.6V390c0-41.7-33.8-75.5-75.6-75.5M512 554.9c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V499.7c0 30.4-24.6 55.2-55.2 55.2M188.2 542.2c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V487c-0.1 30.4-24.9 55.2-55.2 55.2m445.6 207.9l38.7 70.5c1.9 3.6 0.7 8.3-2.9 10.5-3.6 1.9-8.5 0.7-10.5-3.2l-38.9-71.2c-32.8 14.6-69.5 22.9-108.4 22.9-38.7 0-75.4-8-107.9-22.6L365 828c-1.9 3.6-6.8 5.1-10.5 3.2-3.6-1.9-5.1-6.8-3.2-10.5l38.7-70.5c-75.9-39.1-127.2-113.5-127.2-199.1h497.9c0 85.4-51 159.8-126.9 199m-235.3-109c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9 0-11.4-9.3-20.9-20.9-20.9m226.8 0c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9 0-11.4-9.5-20.9-20.9-20.9M264.7 531.7v-358.9c0-32.6 26.3-59.1 59.1-59.1h40.1v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.4V114H549v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V114h40.4c32.6 0 59.1 26.3 59.1 59.1V532l-494.2-0.3zM891 487c0 30.6-24.8 55.2-55.2 55.2-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V487z" horiz-adv-x="1024" />
<glyph glyph-name="android3" unicode="&#58917;" d="M633.472 667.434667h-40.533333v40.533333h40.533333m-202.496-40.533333h-40.490667v40.533333h40.533334m223.914666 74.453333l53.034667 53.077334a20.778667 20.778667 0 0 1 0 28.757333 20.778667 20.778667 0 0 1-28.757333 0L619.306667 804.266667a244.650667 244.650667 0 0 1-107.349334 25.130666c-38.826667 0-75.306667-9.344-107.690666-25.514666L343.893333 864.256a20.309333 20.309333 0 0 1-28.373333 0 20.053333 20.053333 0 0 1 0-28.757333L368.64 782.421333C308.266667 737.877333 269.013333 667.434667 269.013333 586.453333h485.973334c0 80.981333-40.533333 151.850667-100.053334 195.968m201.301334-236.501333a60.757333 60.757333 0 0 1-60.757334-60.714667v-283.477333a60.757333 60.757333 0 0 1 60.757334-60.757333 60.757333 60.757333 0 0 1 60.714666 60.757333V485.205333a60.757333 60.757333 0 0 1-60.714666 60.714667m-688.469334 0a60.757333 60.757333 0 0 1-60.757333-60.714667v-283.477333a60.757333 60.757333 0 0 1 60.757333-60.757333 60.757333 60.757333 0 0 1 60.714667 60.757333V485.205333a60.757333 60.757333 0 0 1-60.714667 60.714667m101.205334-404.949333a40.533333 40.533333 0 0 1 40.533333-40.533334h40.490667v-141.696a60.757333 60.757333 0 0 1 60.714666-60.757333 60.757333 60.757333 0 0 1 60.757334 60.757333v141.738667h80.981333v-141.738667a60.757333 60.757333 0 0 1 60.757333-60.757333 60.757333 60.757333 0 0 1 60.757334 60.757333v141.738667h40.490666a40.533333 40.533333 0 0 1 40.533334 40.490667V545.92H268.970667z" horiz-adv-x="1024" />
<glyph glyph-name="Android" unicode="&#59092;"
d="M512 192.7c-41.8 0-75.6 34-75.6 75.6V499.7c0 41.6 33.8 75.6 75.6 75.6 20.2 0 39.1-7.8 53.5-22.1 14.3-14.3 22.1-33.3 22.1-53.5v-231.5c0-20.2-7.8-39.1-22.1-53.5-14.4-14-33.3-22-53.5-22M243.1 400c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.4 30.6 0 55.2 24.8 55.2 55.4V344.9c0 30.3-24.8 55.1-55.2 55.1m593-11.4H297.3V409c0 83.4 45.5 160.9 119.9 206.9l-28.9 52.5c-3.6 6.1-4.4 14.1-2.4 21.2 2.2 7.1 7.1 13.4 13.6 16.8 4.1 2.4 8.8 3.6 13.4 3.6 10.2 0 19.7-5.6 24.6-14.6l30.4-55.2c31.4 11.4 64.4 17.3 98.7 17.3 34.8 0 68.1-5.8 99.4-17.5l30.1 55.4c4.9 9 14.3 14.6 24.6 14.6 4.6 0 9.2-1.2 13.4-3.4 6.8-3.6 11.7-9.7 13.6-17 2.2-7.3 1.2-14.8-2.4-21.4l-28.9-52.8c74.4-46 119.9-123.5 119.9-206.9v-19.9h-0.2zM633.8 442.7l38.7 70.5c1.9 3.6 0.7 8.5-2.9 10.5-3.9 1.9-8.5 0.7-10.5-3.2l-38.9-71.2c-32.8 14.6-69.5 22.9-108.2 22.6-38.7 0-75.4-8-107.9-22.6l-38.9 71c-1.9 3.6-6.8 5.1-10.5 3.2s-5.1-6.8-3.2-10.5l38.7-70.5C314.3 403.4 263 329 263 243.4h498c-0.3 85.8-51.3 160.2-127.2 199.3M398.5 333.8c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9s-9.3-20.9-20.9-20.9m226.8 0c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9s-9.5-20.9-20.9-20.9M419.3 66c-41.6 0-75.6 33.8-75.6 75.6V243.7h-19.9c-21.2 0-41.1 8.3-56.2 23.1-15.1 15.1-23.3 34.8-23.1 56.2V702h535.1v-379c0-43.8-35.5-79.3-79.3-79.3h-19.9v-102.1c0-41.6-33.8-75.6-75.6-75.6-20.2 0-39.1 7.8-53.5 22.1-14.3 14.3-22.1 33.3-22.1 53.5V243.7h-34v-102.1c-0.3-41.6-34.4-75.6-75.9-75.6M189 307.7c0-32.6 26.3-59.1 59.1-59.1h40.1V126c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.4V248.8h74.6v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V248.8H624c32.6 0 59.1 26.5 59.1 59.1V666.8H188.8l0.2-359.1z m570.6 6.8c-41.6 0-75.6 33.8-75.6 75.6V621.5c0 41.8 33.8 75.6 75.6 75.6s75.6-33.8 75.6-75.6V390c0-41.7-33.8-75.5-75.6-75.5M512 554.9c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V499.7c0 30.4-24.6 55.2-55.2 55.2M188.2 542.2c-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V487c-0.1 30.4-24.9 55.2-55.2 55.2m445.6 207.9l38.7 70.5c1.9 3.6 0.7 8.3-2.9 10.5-3.6 1.9-8.5 0.7-10.5-3.2l-38.9-71.2c-32.8 14.6-69.5 22.9-108.4 22.9-38.7 0-75.4-8-107.9-22.6L365 828c-1.9 3.6-6.8 5.1-10.5 3.2-3.6-1.9-5.1-6.8-3.2-10.5l38.7-70.5c-75.9-39.1-127.2-113.5-127.2-199.1h497.9c0 85.4-51 159.8-126.9 199m-235.3-109c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9 0-11.4-9.3-20.9-20.9-20.9m226.8 0c-11.4 0-20.9 9.2-20.9 20.9 0 11.4 9.2 20.9 20.9 20.9 11.4 0 20.9-9.5 20.9-20.9 0-11.4-9.5-20.9-20.9-20.9M264.7 531.7v-358.9c0-32.6 26.3-59.1 59.1-59.1h40.1v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.4V114H549v-122.5c0-30.4 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V114h40.4c32.6 0 59.1 26.3 59.1 59.1V532l-494.2-0.3zM891 487c0 30.6-24.8 55.2-55.2 55.2-30.6 0-55.2-24.8-55.2-55.2v-231.5c0-30.6 24.8-55.2 55.2-55.2 30.6 0 55.2 24.8 55.2 55.2V487z"
horiz-adv-x="1024"/>
<glyph glyph-name="android3" unicode="&#58917;"
d="M633.472 667.434667h-40.533333v40.533333h40.533333m-202.496-40.533333h-40.490667v40.533333h40.533334m223.914666 74.453333l53.034667 53.077334a20.778667 20.778667 0 0 1 0 28.757333 20.778667 20.778667 0 0 1-28.757333 0L619.306667 804.266667a244.650667 244.650667 0 0 1-107.349334 25.130666c-38.826667 0-75.306667-9.344-107.690666-25.514666L343.893333 864.256a20.309333 20.309333 0 0 1-28.373333 0 20.053333 20.053333 0 0 1 0-28.757333L368.64 782.421333C308.266667 737.877333 269.013333 667.434667 269.013333 586.453333h485.973334c0 80.981333-40.533333 151.850667-100.053334 195.968m201.301334-236.501333a60.757333 60.757333 0 0 1-60.757334-60.714667v-283.477333a60.757333 60.757333 0 0 1 60.757334-60.757333 60.757333 60.757333 0 0 1 60.714666 60.757333V485.205333a60.757333 60.757333 0 0 1-60.714666 60.714667m-688.469334 0a60.757333 60.757333 0 0 1-60.757333-60.714667v-283.477333a60.757333 60.757333 0 0 1 60.757333-60.757333 60.757333 60.757333 0 0 1 60.714667 60.757333V485.205333a60.757333 60.757333 0 0 1-60.714667 60.714667m101.205334-404.949333a40.533333 40.533333 0 0 1 40.533333-40.533334h40.490667v-141.696a60.757333 60.757333 0 0 1 60.714666-60.757333 60.757333 60.757333 0 0 1 60.757334 60.757333v141.738667h80.981333v-141.738667a60.757333 60.757333 0 0 1 60.757333-60.757333 60.757333 60.757333 0 0 1 60.757334 60.757333v141.738667h40.490666a40.533333 40.533333 0 0 1 40.533334 40.490667V545.92H268.970667z"
horiz-adv-x="1024"/>
</font>
</defs></svg>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

@ -113,7 +113,11 @@
devices() {
this.setfunactive('devices', 57);
if (this.appinfos.issupersign) {
this.$router.push({"name":'FirSuperSignBase', params: {act: "useddevices"},query:{bundleid:this.appinfos.bundle_id}})
this.$router.push({
"name": 'FirSuperSignBase',
params: {act: "useddevices"},
query: {bundleid: this.appinfos.bundle_id}
})
} else {
this.$router.push({name: 'FirAppInfosdevices'});
}
@ -131,9 +135,7 @@
return ftype
},
},
computed: {
}, mounted() {
computed: {}, mounted() {
getappinfos(data => {
if (data.code === 1000) {

@ -191,9 +191,11 @@
let certinfo = data.data;
this.uploadtostorage(file, certinfo);
}
},{'methods':'GET','data':{'app_id':this.currentapp.app_id,'upload_key':file.name,'ftype':'app'}});
}
else{
}, {
'methods': 'GET',
'data': {'app_id': this.currentapp.app_id, 'upload_key': file.name, 'ftype': 'app'}
});
} else {
this.$message.error('上传应用图片大小不能超过 2MB!');
}
} else {

@ -35,9 +35,7 @@
udidlists: []
}
},
methods: {
},
methods: {},
mounted() {
this.$store.dispatch('doappInfoIndex', [[57, 57], [57, 57]]);
if (!this.currentapp.app_id) {
@ -50,8 +48,7 @@
this.currentapp = this.$store.state.currentapp;
this.udidlists = this.currentapp.master_release.udid;
}
},computed:{
}
}, computed: {}
}
</script>

@ -54,7 +54,9 @@
inactive-value="off">
</el-switch>
</el-tooltip>
<el-button @click="clean_app" v-if="currentapp.issupersign === 0 && currentapp.count !== 0" style="margin-left: 20px" size="small" type="info" plain>清理开发者账户脏数据</el-button>
<el-button @click="clean_app" v-if="currentapp.issupersign === 0 && currentapp.count !== 0"
style="margin-left: 20px" size="small" type="info" plain>清理开发者账户脏数据
</el-button>
</el-form-item>
@ -270,8 +272,7 @@
'$store.state.currentapp': function () {
this.appinit();
},
},computed:{
}
}, computed: {}
}
</script>

@ -371,7 +371,8 @@
<i class="icon-eye el-icon-view"></i> 预览
</el-button>
<el-button v-if="r.issupersign" @click="DeleteApp(r)" class="btn btn-remove" icon="el-icon-loading"
<el-button v-if="r.issupersign" @click="DeleteApp(r)" class="btn btn-remove"
icon="el-icon-loading"
circle></el-button>
<el-button v-else @click="DeleteApp(r)" class="btn btn-remove" icon="el-icon-delete"
@ -717,17 +718,6 @@
getDelappTitle() {
return `删除应用 ${this.delapp.name}`
},
getBH: function () {
let sch = this.$refs.appmain.scrollHeight;
if (sch === 0 || sch < window.innerHeight) {
sch = window.innerHeight;
} else {
sch += 280;
}
return sch;
}
},
filters: {
getiOStype: function (type) {
@ -781,7 +771,6 @@
}, mounted() {
this.$store.dispatch('doucurrentapp', {});
this.getappsFun({});
// window.addEventListener('scroll',this.auto_load);
},
destroyed() {
window.removeEventListener('scroll', this.auto_load, false);

@ -32,11 +32,14 @@
</span>
</div>
<p v-if="currentappinfo.issupersign" class="scan-tips wrapper icon-warp">超级签</p>
<p v-else class="scan-tips wrapper icon-warp" >{{ mcurrentappinfo.release_type|getiOStype }}</p>
<p v-else class="scan-tips wrapper icon-warp">{{
mcurrentappinfo.release_type|getiOStype }}</p>
<h1 class="name wrapper">
<span class="icon-warp" style="margin-left:0px">
<i v-if="currentappinfo.type === 0 && agent !== ''" class="iconfont icon-android2"/>
<i v-if="currentappinfo.type === 1 && agent !== ''" class="iconfont icon-ios"/>
<i v-if="currentappinfo.type === 0 && agent !== ''"
class="iconfont icon-android2"/>
<i v-if="currentappinfo.type === 1 && agent !== ''"
class="iconfont icon-ios"/>
{{ currentappinfo.name }}
</span>
@ -46,7 +49,8 @@
class="text-black">{{ full_url }}</span></p>
<div class="release-info">
<p>{{ mcurrentappinfo.app_version }}Build {{ mcurrentappinfo.build_version }}- {{ mcurrentappinfo.binary_size }}</p>
<p>{{ mcurrentappinfo.app_version }}Build {{ mcurrentappinfo.build_version }}-
{{ mcurrentappinfo.binary_size }}</p>
<p>更新于{{ mcurrentappinfo.created_time |formatTime}}</p>
<p class="version" v-if="mcurrentappinfo.changelog && agent === ''">
更新日志{{ mcurrentappinfo.changelog }}
@ -60,14 +64,23 @@
<button type="button" v-else-if="wrong">{{ msg }}</button>
<div v-else>
<button v-if="isdownload" disabled="" class="loading" style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;">&nbsp;</button>
<button v-if="isdownload" disabled="" class="loading"
style="min-width: 42px; width: 42px; padding: 21px 0; border-top-color: transparent; border-left-color: transparent;">
&nbsp;
</button>
<div v-else>
<div v-if="currentappinfo.need_password" style="margin:0 auto; width:166px">
<el-input prefix-icon="el-icon-lock" clearable="true" placeholder="请输入密码" v-model="password" icon="el-icon-loadings" type="primary" :underline="false"> </el-input>
<div v-if="currentappinfo.need_password"
style="margin:0 auto; width:166px">
<el-input prefix-icon="el-icon-lock" clearable="true"
placeholder="请输入密码" v-model="password"
icon="el-icon-loadings" type="primary"
:underline="false"></el-input>
</div>
<el-divider v-if="currentappinfo.need_password"></el-divider>
<button @click="download">
<el-link icon="el-icon-loadings" type="primary" :underline="false"> 下载安装 </el-link>
<el-link icon="el-icon-loadings" type="primary" :underline="false">
下载安装
</el-link>
</button>
</div>
@ -203,8 +216,7 @@
}
window.location.href = this.downloadurl;
}
else {
} else {
this.isdownload = false;
this.password = '';
this.$message({
@ -319,8 +331,7 @@
if (this.mcurrentappinfo.binary_url && this.agent !== '' && this.wrong === false) {
window.location.href = this.mcurrentappinfo.binary_url
}
}
else {
} else {
this.$message({
message: data.msg,
type: 'error',
@ -1406,7 +1417,6 @@
}
.app_bottom_fixed img {
width: 100%;
max-height: 80px

@ -15,7 +15,9 @@
</el-col>
<el-col :span="2" :push="4">
<div class="block"><el-avatar :size="66" :src="$store.state.userinfo.head_img"></el-avatar></div>
<div class="block">
<el-avatar :size="66" :src="$store.state.userinfo.head_img"></el-avatar>
</div>
</el-col>
<el-col :span="4" :push="4">
<el-dropdown style="padding-top: 12px;" @command="handleCommand">
@ -45,6 +47,7 @@
<script>
import {logout} from '../restful'
export default {
name: "FirHeader",
data() {
@ -64,8 +67,7 @@ import {logout} from '../restful'
this.$store.dispatch('doucurrentapp', {});
this.$router.push({"name": 'FirSuperSignBase', params: {act: "iosdeveloper"}})
}
else if(command === 'exit'){
} else if (command === 'exit') {
logout(data => {
if (data.code === 1000) {
this.$message.success("退出成功");

@ -1,7 +1,8 @@
<template>
<el-main>
<el-dialog :title="title" :visible.sync="dialogaddDeveloperVisible" :destroy-on-close="true" :close-on-click-modal="false" style="text-align:center">
<el-dialog :title="title" :visible.sync="dialogaddDeveloperVisible" :destroy-on-close="true"
:close-on-click-modal="false" style="text-align:center">
<el-form ref="storageinfoform" :model="editdeveloperinfo"
label-width="80px" style="margin:0 auto;">
@ -21,8 +22,15 @@
<el-input v-model="editdeveloperinfo.description"></el-input>
</el-form-item>
<div style="">
<el-button v-if="isedit && editdeveloperinfo.is_actived" @click="syncdevices">同步设备信息</el-button>
<el-button v-if="isedit && editdeveloperinfo.is_actived && !editdeveloperinfo.certid" @click="isocertcert">手动创建证书</el-button>
<el-button v-if="isedit && editdeveloperinfo.is_actived" size="small" @click="syncdevices">同步设备信息
</el-button>
<el-button v-if="isedit && editdeveloperinfo.is_actived && !editdeveloperinfo.certid" size="small"
@click="isocertcert">手动创建证书
</el-button>
<el-button v-if="isedit && editdeveloperinfo.is_actived" type="danger" size="small"
@click="activedeveloperFun(editdeveloperinfo,'checkauth')">开发者账户激活检测
</el-button>
<el-button @click="updateorcreate">保存</el-button>
<el-button @click="canceledit">取消</el-button>
</div>
@ -37,14 +45,20 @@
:visible.sync="codeactiveVisible"
width="30%"
center>
<div>
<el-input
placeholder="一般为6位数字"
v-model="authcode">
</el-input>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="codeactiveVisible = false"> </el-button>
<el-button type="primary" @click="codeactiveVisible = false"> </el-button>
<el-button type="primary" @click="inputcode"> </el-button>
</span>
</el-dialog>
<el-tabs v-model="activeName" type="border-card" @tab-click="handleClick" tab-position="top">
<el-tab-pane label="开发者账户" name="iosdeveloper">
<el-input
@ -52,13 +66,19 @@
v-model="appidseach"
clearable
placeholder="输入用户APPID"/>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">搜索</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">
搜索
</el-button>
<div style="width: 40%;margin-right: 30px;float:right">
<el-link :underline="false">总设备量{{ developer_used_info.all_usable_number}} 已经使用平台{{ developer_used_info.all_use_number}} 其他{{developer_used_info.other_used_sum}} 还剩{{developer_used_info.all_usable_number- developer_used_info.flyapp_used_sum}} 可用</el-link>
<el-link :underline="false">总设备量{{ developer_used_info.all_usable_number}} 已经使用平台{{
developer_used_info.all_use_number}} 其他{{developer_used_info.other_used_sum}}
还剩{{developer_used_info.all_usable_number- developer_used_info.flyapp_used_sum}} 可用
</el-link>
<el-progress
type="line"
:color="developer_usedColor"
:text-inside="true" :stroke-width="18" :percentage="percentage" status="success"></el-progress>
:text-inside="true" :stroke-width="18" :percentage="percentage"
status="success"></el-progress>
</div>
<el-table
@ -76,7 +96,9 @@
<el-popover trigger="hover" placement="top">
<p>开发者账户已使用设备数: {{ scope.row.developer_used_number }}</p>
<p>开发者账户可用设备数: {{ 100-scope.row.developer_used_number }}</p>
<p>由于您设置可用设备数: {{ scope.row.usable_number}} ,所以现在可用设备数: {{ scope.row.usable_number-scope.row.developer_used_number > 0 ?scope.row.usable_number-scope.row.developer_used_number :0 }}</p>
<p>由于您设置可用设备数: {{ scope.row.usable_number}} ,所以现在可用设备数: {{
scope.row.usable_number-scope.row.developer_used_number > 0
?scope.row.usable_number-scope.row.developer_used_number :0 }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.email }}</el-tag>
@ -91,19 +113,41 @@
width="110">
<template slot-scope="scope">
<el-button v-if="scope.row.is_actived === true" type="success" size="small">已激活</el-button>
<el-button v-else type="danger" size="small" @click="activedeveloperFun(scope.row)">点击激活</el-button>
<el-button v-else type="danger" size="small"
@click="activedeveloperFun(scope.row,'preactive')">点击激活
</el-button>
</template>
</el-table-column>
<el-table-column
prop="certid"
label="账户状态"
width="100">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p v-if="!scope.row.certid && scope.row.is_actived === true">开发证书不可用请在编辑中手动创建开发者证书</p>
<p v-if="!scope.row.certid && scope.row.is_actived !== true">请先激活开发者账户</p>
<p v-if="scope.row.certid && scope.row.is_actived === true">账户已经启用</p>
<div slot="reference" class="name-wrapper">
<el-button v-if="scope.row.certid " type="success" size="small">可用</el-button>
<el-button v-else type="danger" size="small">不可用</el-button>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
prop="usable_number"
label="可用设备数"
label="可用设备"
width="100">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>可用设备数: {{ scope.row.usable_number-scope.row.developer_used_number > 0 ?scope.row.usable_number-scope.row.developer_used_number :0}}</p>
<p>可用设备数: {{ scope.row.usable_number-scope.row.developer_used_number > 0
?scope.row.usable_number-scope.row.developer_used_number :0}}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium"> {{ scope.row.usable_number-scope.row.developer_used_number > 0 ?scope.row.usable_number-scope.row.developer_used_number :0 }}</el-tag>
<el-tag size="medium"> {{ scope.row.usable_number-scope.row.developer_used_number >
0 ?scope.row.usable_number-scope.row.developer_used_number :0 }}
</el-tag>
</div>
</el-popover>
</template>
@ -111,8 +155,8 @@
<el-table-column
prop="use_number"
label="已消耗设备数"
width="120">
label="设备消耗"
width="100">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>开发者账户已使用设备数本平台: {{ scope.row.use_number }}</p>
@ -143,11 +187,13 @@
<el-button
size="mini"
@click="handleEditDeveloper(scope.row)">编辑</el-button>
@click="handleEditDeveloper(scope.row)">编辑
</el-button>
<el-button
size="mini"
type="danger"
@click="handleDeleteDeveloper(scope.row)">删除</el-button>
@click="handleDeleteDeveloper(scope.row)">删除
</el-button>
</template>
</el-table-column>
@ -155,7 +201,31 @@
</el-tab-pane>
<el-tab-pane label="添加开发者" name="adddeveloper">添加开发者</el-tab-pane>
<el-tab-pane label="添加开发者" name="adddeveloper" style="text-align:center">
<el-form ref="storageinfoform" :model="editdeveloperinfo"
label-width="80px" style="margin:0 auto;">
<el-form-item label-width="110px" label="APP_ID">
<el-input :disabled='isedit' v-model="editdeveloperinfo.email"></el-input>
</el-form-item>
<el-form-item label-width="110px" label="password">
<el-input v-model="editdeveloperinfo.password" :placeholder="placeholder"></el-input>
</el-form-item>
<el-form-item label-width="110px" label="设备数量">
<el-input v-model="editdeveloperinfo.usable_number"></el-input>
</el-form-item>
<el-form-item label-width="110px" label="备注">
<el-input v-model="editdeveloperinfo.description"></el-input>
</el-form-item>
<div style="">
<el-button @click="updateorcreate">添加</el-button>
<el-button @click="canceledit">取消</el-button>
</div>
</el-form>
</el-tab-pane>
<el-tab-pane label="设备消耗" name="useddevices">
<el-input
style="width: 30%;margin-right: 30px;margin-bottom: 10px"
@ -172,7 +242,9 @@
v-model="appidseach"
clearable
placeholder="输入用户APPID"/>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">搜索</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">
搜索
</el-button>
<el-table
:data="app_devices_lists"
@ -226,7 +298,9 @@
v-model="Bundleidsearch"
clearable
placeholder="输入BundleID"/>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">搜索</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleCurrentChange(pagination.currentPage)">
搜索
</el-button>
<el-table
@ -286,7 +360,8 @@
<el-button
size="mini"
type="danger"
@click="udidDeleteFun(scope)">删除</el-button>
@click="udidDeleteFun(scope)">删除
</el-button>
</template>
</el-table-column>
</el-table>
@ -333,7 +408,8 @@
pagination: {"currentPage": 1, "total": 0, "pagesize": 10},
developer_used_info: {"all_usable_number": 0, "other_used_sum": 0, "all_use_number": 0},
percentage: 0,
authcode: "",
authemail: "",
}
},
methods: {
@ -359,37 +435,47 @@
},
handleSizeChange(val) {
this.pagination.pagesize = val;
this.get_data_from_tabname(this.activeName,{"size":this.pagination.pagesize,"page":this.pagination.currentPage})
this.get_data_from_tabname(this.activeName, {
"size": this.pagination.pagesize,
"page": this.pagination.currentPage
})
},
handleCurrentChange(val) {
this.pagination.currentPage = val;
this.get_data_from_tabname(this.activeName,{"size":this.pagination.pagesize,"page":this.pagination.currentPage})
this.get_data_from_tabname(this.activeName, {
"size": this.pagination.pagesize,
"page": this.pagination.currentPage
})
},
syncdevices() {
this.iosdeveloperFun({"methods":"PUT","data":{"email":this.editdeveloperinfo.email,"act":"syncdevice"}});
this.iosdeveloperFun({
"methods": "PUT",
"data": {"email": this.editdeveloperinfo.email, "act": "syncdevice"}
});
},
isocertcert() {
this.iosdeveloperFun({"methods":"PUT","data":{"email":this.editdeveloperinfo.email,"act":"ioscert"}});
},
inputcode(developer){
this.$prompt('请输入验证码', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal:false,
}).then(({ value }) => {
if(value.toString().length>5 && IsNum(value)){
this.iosdeveloperFun({"methods":"PUT","data":{"email":developer.email,"act":"nowactive","code":value.replace(/^\s+|\s+$/g, "")}});
}
}).catch(() => {
this.$message({
type: 'info',
message: '取消激活'
this.iosdeveloperFun({
"methods": "PUT",
"data": {"email": this.editdeveloperinfo.email, "act": "ioscert"}
});
},
inputcode() {
this.authcode = this.authcode.replace(/^\s+|\s+$/g, "");
if (this.authcode.toString().length > 5 && IsNum(this.authcode)) {
this.iosdeveloperFun({
"methods": "PUT",
"data": {"email": this.authemail, "act": "nowactive", "code": this.authcode}
});
this.authcode = "";
this.authemail = ""
}
},
activedeveloperFun(developer){
this.iosdeveloperFun({"methods":"PUT","data":{"email":developer.email,"act":"preactive"}});
this.inputcode(developer)
activedeveloperFun(developer, act) {
this.iosdeveloperFun({"methods": "PUT", "data": {"email": developer.email, "act": act}});
this.codeactiveVisible = true;
this.authemail = developer.email;
// this.inputcode(developer)
},
canceledit() {
this.dialogaddDeveloperVisible = false;
@ -441,8 +527,8 @@
} else if (tabname === "devicesudid") {
this.iosdevicesudidFun('GET', data)
} else if (tabname === "adddeveloper") {
this.title='新增私有开发者账户';
this.dialogaddDeveloperVisible=true;
// this.title='';
// this.dialogaddDeveloperVisible=true;
} else if (tabname === "iosdeveloper") {
this.iosdeveloperFun({"methods": "GET", "data": data})
}
@ -497,15 +583,20 @@
this.$message.success("操作成功");
this.activeName = "iosdeveloper";
this.editdeveloperinfo = {};
}
if (!this.edit && this.editdeveloperinfo.email) {
this.$message.success("添加成功");
this.activeName = "iosdeveloper";
this.editdeveloperinfo = {};
}
else if(data.code === 1008){
} else if (data.code === 1008) {
this.$message.error(data.msg);
}
else {
} else {
this.$message.error("操作失败")
}
if (this.codeactiveVisible) {
this.codeactiveVisible = false;
}
}, params)
},
iosdevicesudidFun(action, data) {

@ -148,11 +148,13 @@
let certinfo = data.data;
this.uploadtostorage(file, certinfo);
}
},{'methods':'GET','data':{'app_id':this.userinfo.uid,'upload_key':file.name,'ftype':'head'}});
}, {
'methods': 'GET',
'data': {'app_id': this.userinfo.uid, 'upload_key': file.name, 'ftype': 'head'}
});
return false;
}
else{
} else {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
@ -188,9 +190,7 @@
'$store.state.userInfoIndex': function () {
this.autoSetInfoIndex();
},
},filters:{
},computed:{
}, filters: {}, computed: {
getuppicurl() {
return getuserpicurl()
}

@ -66,10 +66,12 @@
} else {
this.$message.error('密码修改失败,' + data.msg);
}
},{"methods":'PUT','data':{
}, {
"methods": 'PUT', 'data': {
"oldpassword": this.form.oldpassword,
"surepassword": this.form.surepassword
}});
}
});
} else {
this.$message.error('密码不一致');
}

@ -5,14 +5,16 @@
<el-form-item>
<el-row>
<el-col :span="22">
<el-input v-model="userinfo.username" prefix-icon="el-icon-user" placeholder="用户名" disabled></el-input>
<el-input v-model="userinfo.username" prefix-icon="el-icon-user" placeholder="用户名"
disabled></el-input>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-row>
<el-col :span="18">
<el-input v-model="userinfo.qq" :readonly="editqq !== true" ref="qq" prefix-icon="el-icon-message"
<el-input v-model="userinfo.qq" :readonly="editqq !== true" ref="qq"
prefix-icon="el-icon-message"
placeholder="QQ"></el-input>
</el-col>
<el-col :span="2">
@ -87,6 +89,7 @@
<script>
import {userinfos} from '../restful'
export default {
name: "FirUserProfileInfo",
data() {

@ -1,7 +1,8 @@
<template>
<div style="text-align:center">
<h2 v-if="is_admin_storage">管理员存储您配置的存储将决定其他用户配置的默认存储请谨慎修改</h2>
<el-dialog :title="title" :visible.sync="dialogstorageVisible" :destroy-on-close="true" :close-on-click-modal="false">
<el-dialog :title="title" :visible.sync="dialogstorageVisible" :destroy-on-close="true"
:close-on-click-modal="false">
<el-form v-if="editstorageinfo.id !==-1" ref="storageinfoform" :model="editstorageinfo"
label-width="80px" style="margin:0 auto;">
@ -38,7 +39,8 @@
</el-form-item>
<el-form-item label-width="110px" label="endpoint">
<el-input :disabled='disabled' v-model="editstorageinfo.additionalparameter.endpoint"></el-input>
<el-input :disabled='disabled'
v-model="editstorageinfo.additionalparameter.endpoint"></el-input>
</el-form-item>
</div>
@ -71,7 +73,9 @@
</el-option>
</el-option-group>
</el-select>
<el-button style="margin-left: 10px" round type="info" icon="el-icon-thumb" @click="change_storage_info">保存</el-button>
<el-button style="margin-left: 10px" round type="info" icon="el-icon-thumb"
@click="change_storage_info">保存
</el-button>
<!-- <el-button-group style="margin-left: 10px">-->
<!-- <el-button round type="info" icon="el-icon-edit" @click="change_storage_info"></el-button>-->
@ -84,7 +88,8 @@
<el-form-item label-width="110px" label="存储类型">
<el-select :disabled='Sdisabled' v-model="storageinfo.storage_type" placeholder="存储类型"
style="margin-left: -60px">
<el-option v-for="st in storage_list" :key="st.id" :label="st.name" :value="st.id"></el-option>
<el-option v-for="st in storage_list" :key="st.id" :label="st.name"
:value="st.id"></el-option>
</el-select>
</el-form-item>
@ -115,7 +120,8 @@
</el-form-item>
<el-form-item label-width="110px" label="endpoint">
<el-input :disabled='Sdisabled' v-model="storageinfo.additionalparameter.endpoint"></el-input>
<el-input :disabled='Sdisabled'
v-model="storageinfo.additionalparameter.endpoint"></el-input>
</el-form-item>
<el-form-item label-width="110px" label="备注">
@ -175,7 +181,9 @@
width="120">
<template slot-scope="scope">
<div v-if="scope.row.id === org_storage_id">
<el-button v-if="scope.row.id === org_storage_id" @click="showstorage(scope.row)" type="success" size="small">使用中</el-button>
<el-button v-if="scope.row.id === org_storage_id" @click="showstorage(scope.row)"
type="success" size="small">使用中
</el-button>
</div>
<div v-else>
<el-button @click="showstorage(scope.row)" type="text" size="small">查看</el-button>

@ -4,6 +4,7 @@ import router from "@/router";
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import Vuex from 'vuex'
const qiniu = require('qiniu-js');
Vue.prototype.qiniu = qiniu;

@ -1,6 +1,7 @@
import Axios from 'axios'
import VueCookies from 'vue-cookies'
import router from "../router";
const https = require('https');
const Base64 = require('js-base64').Base64;
Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
@ -11,6 +12,8 @@ Axios.defaults.httpsAgent = new https.Agent({
const DOMAIN = 'https://fly.harmonygames.cn';
// const DOMAIN = 'https://testapp.harmonygames.cn';
// const DOMAIN = 'http://172.16.133.34:8000';
const APIPATH = '/api/v1/fir/server';
let USERSEVER = DOMAIN + APIPATH;
@ -41,20 +44,7 @@ export function set_auth_token() {
set_auth_token();
function getData(methods = true, url, params = {}, callBack, load, isCode = false) {
if (methods === "DELETE") {
Axios
.delete(url, {params:params})
.then(function (response) {
if (isCode) {
callBack(response.data);
} else {
callBack(response.data.data);
}
})
.catch(function (error) {
function ErrorMsg(error) {
if (error && error.response) {
switch (error.response.status) {
case 400:
@ -96,16 +86,35 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals
} else {
error.message = '连接服务器失败!';
}
if (error.response && error.response.status === 403) {
router.push({name: 'FirLogin'});
}
if (error.message === 'Network Error') {
alert('网络连接失败');
} else {
alert(error)
}
}
function getData(methods = true, url, params = {}, callBack, load, isCode = false) {
if (methods === "DELETE") {
Axios
.delete(url, {params: params})
.then(function (response) {
if (isCode) {
callBack(response.data);
} else {
callBack(response.data.data);
}
})
.catch(function (error) {
ErrorMsg(error);
callBack(null);
});
}
else if (methods === "PUT") {
} else if (methods === "PUT") {
Axios
.put(url, params)
.then(function (response) {
@ -116,16 +125,11 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals
}
})
.catch(function (error) {
// eslint-disable-next-line no-console
console.log(error, error.response);
ErrorMsg(error);
callBack(null);
});
}
else if (methods === 'POST') {
} else if (methods === 'POST') {
Axios
.post(url, params)
.then(function (response) {
@ -137,8 +141,7 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals
})
.catch(function (error) {
// eslint-disable-next-line no-console
console.log(error, error.response);
ErrorMsg(error);
callBack(null);
});
} else {
@ -148,11 +151,8 @@ function getData(methods = true, url, params = {}, callBack, load, isCode = fals
callBack(response.data);
})
.catch(function (error) {
// eslint-disable-next-line no-console
console.log(error, error.response);
if(error.response && error.response.status === 403){
router.push({name: 'FirLogin'});
}
ErrorMsg(error);
callBack(null);
});
}
@ -349,6 +349,7 @@ export function userinfos(callBack, params, load = true) {
export function getuserpicurl() {
return USERSEVER + '/userinfo'
}
export function getapppicurl(app_id) {
return USERSEVER + '/apps/' + app_id
}

@ -14,7 +14,6 @@ export function getScrollTop(){
}
//文档的总高度
export function getScrollHeight() {
let scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0;
@ -173,6 +172,7 @@ export function uploadaliyunoss(file,certinfo,app,successcallback,processcallbac
import {uploadstorage} from '../restful'
export function uploadlocalstorage(file, certinfo, app, successcallback, processcallback) {
uploadstorage(certinfo, file, successcallback, processcallback)
@ -185,12 +185,10 @@ export function removeAaary(_arr, _obj) {
if (i == 0) {
_arr.shift(); //删除并返回数组的第一个元素
return _arr;
}
else if (i == length - 1) {
} else if (i == length - 1) {
_arr.pop(); //删除并返回数组的最后一个元素
return _arr;
}
else {
} else {
_arr.splice(i, 1); //删除下标为i的元素
return _arr;
}

@ -3,7 +3,6 @@ from django.contrib import admin
# Register your models here.
from .models import *
admin.site.register(UserInfo)
admin.site.register(Apps)
admin.site.register(AppReleaseInfo)
@ -15,4 +14,3 @@ admin.site.register(AppIOSDeveloperInfo)
admin.site.register(APPSuperSignUsedInfo)
admin.site.register(APPToDeveloper)
admin.site.register(UDIDsyncDeveloper)

@ -7,7 +7,6 @@ import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
@ -21,28 +20,39 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('is_superuser', models.BooleanField(default=False,
help_text='Designates that this user has all permissions without explicitly assigning them.',
verbose_name='superuser status')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_staff', models.BooleanField(default=False,
help_text='Designates whether the user can log into this admin site.',
verbose_name='staff status')),
('username', models.CharField(max_length=64, unique=True, verbose_name='用户名')),
('email', models.EmailField(blank=True, max_length=255, null=True, unique=True, verbose_name='email address')),
('email',
models.EmailField(blank=True, max_length=255, null=True, unique=True, verbose_name='email address')),
('uid', models.CharField(db_index=True, max_length=64, unique=True)),
('mobile', models.BigIntegerField(help_text='用于手机验证码登录', null=True, unique=True, verbose_name='手机')),
('qq', models.BigIntegerField(blank=True, db_index=True, null=True, verbose_name='QQ')),
('is_active', models.BooleanField(default=True, verbose_name='账户状态,默认启用')),
('job', models.TextField(blank=True, max_length=128, null=True, verbose_name='职位')),
('company', models.CharField(blank=True, max_length=128, null=True, verbose_name='公司')),
('gender', models.SmallIntegerField(choices=[(0, '保密'), (1, ''), (2, '')], default=0, verbose_name='性别')),
('gender',
models.SmallIntegerField(choices=[(0, '保密'), (1, ''), (2, '')], default=0, verbose_name='性别')),
('head_img', models.CharField(default='head_img.jpeg', max_length=256, verbose_name='个人头像')),
('role', models.SmallIntegerField(choices=[(0, '普通会员'), (1, 'VIP'), (2, 'SVIP'), (3, '管理员')], default=0, verbose_name='角色')),
('role', models.SmallIntegerField(choices=[(0, '普通会员'), (1, 'VIP'), (2, 'SVIP'), (3, '管理员')], default=0,
verbose_name='角色')),
('memo', models.TextField(blank=True, default=None, null=True, verbose_name='备注')),
('date_joined', models.DateTimeField(auto_now_add=True, verbose_name='注册时间')),
('download_times', models.IntegerField(default=100, verbose_name='下载次数')),
('all_download_times', models.BigIntegerField(default=0, verbose_name='总共下载次数')),
('domain_name', models.CharField(blank=True, max_length=64, null=True, verbose_name='域名')),
('history_release_limit', models.IntegerField(blank=True, default=10, null=True, verbose_name='app 历史记录版本')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('history_release_limit',
models.IntegerField(blank=True, default=10, null=True, verbose_name='app 历史记录版本')),
('groups', models.ManyToManyField(blank=True,
help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
related_name='user_set', related_query_name='user', to='auth.Group',
verbose_name='groups')),
],
options={
'verbose_name': '账户信息',
@ -57,7 +67,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64, unique=True, verbose_name='开发者标识')),
('email', models.EmailField(blank=True, max_length=64, null=True, unique=True, verbose_name='email address')),
('email',
models.EmailField(blank=True, max_length=64, null=True, unique=True, verbose_name='email address')),
('password', models.CharField(max_length=64)),
('is_actived', models.BooleanField(default=False, verbose_name='是否已经激活')),
('certid', models.CharField(blank=True, max_length=64, null=True, verbose_name='超级签名自动创建证书ID')),
@ -66,7 +77,8 @@ class Migration(migrations.Migration):
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('description', models.TextField(blank=True, default='', null=True, verbose_name='备注')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户ID')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
options={
'verbose_name': '苹果开发者账户',
@ -89,8 +101,10 @@ class Migration(migrations.Migration):
('issupersign', models.BigIntegerField(default=False, verbose_name='是否超级签名包')),
('description', models.TextField(blank=True, default=None, null=True, verbose_name='描述')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('has_combo', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='combo_app_info', to='api.Apps', verbose_name='关联应用')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户ID')),
('has_combo', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL,
related_name='combo_app_info', to='api.Apps', verbose_name='关联应用')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
options={
'verbose_name': '应用信息',
@ -106,7 +120,8 @@ class Migration(migrations.Migration):
('address', models.CharField(blank=True, max_length=128, null=True, verbose_name='联系地址')),
('mobile', models.BigIntegerField(blank=True, null=True, verbose_name='联系电话')),
('date_verify', models.DateTimeField(auto_now_add=True, verbose_name='认证时间')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='verify_info', to=settings.AUTH_USER_MODEL, verbose_name='关联用户')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='verify_info',
to=settings.AUTH_USER_MODEL, verbose_name='关联用户')),
],
options={
'verbose_name': '实名认证',
@ -119,7 +134,8 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('access_token', models.CharField(max_length=64, unique=True)),
('created', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='关联用户')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token',
to=settings.AUTH_USER_MODEL, verbose_name='关联用户')),
],
),
migrations.CreateModel(
@ -136,7 +152,8 @@ class Migration(migrations.Migration):
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('is_signed', models.BooleanField(default=False, verbose_name='是否完成签名打包')),
('binary_file', models.CharField(blank=True, max_length=128, null=True, verbose_name='签名包名称')),
('app_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('app_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
],
options={
'verbose_name': '设备详情',
@ -150,10 +167,15 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('app_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('developerid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo', verbose_name='所使用苹果开发者账户')),
('udid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppUDID', verbose_name='所消耗的udid')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户ID')),
('app_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('developerid',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo',
verbose_name='所使用苹果开发者账户')),
('udid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppUDID',
verbose_name='所消耗的udid')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
options={
'verbose_name': '设备使用统计',
@ -165,17 +187,26 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=64, null=True, verbose_name='存储名字')),
('storage_type', models.SmallIntegerField(choices=[(0, '本地存储'), (1, '七牛云存储'), (2, '阿里云存储'), (3, '默认存储')], default=3, verbose_name='存储类型')),
('storage_type',
models.SmallIntegerField(choices=[(0, '本地存储'), (1, '七牛云存储'), (2, '阿里云存储'), (3, '默认存储')], default=3,
verbose_name='存储类型')),
('access_key', models.CharField(blank=True, max_length=128, null=True, verbose_name='存储访问key')),
('secret_key', models.CharField(blank=True, max_length=128, null=True, verbose_name='存储访问secret')),
('bucket_name', models.CharField(blank=True, max_length=128, null=True, verbose_name='存储空间bucket_name')),
('domain_name', models.CharField(blank=True, help_text='fly-storage.dvcloud.xin,可以自定义端口', max_length=128, null=True, verbose_name='下载域名')),
(
'bucket_name',
models.CharField(blank=True, max_length=128, null=True, verbose_name='存储空间bucket_name')),
('domain_name',
models.CharField(blank=True, help_text='fly-storage.dvcloud.xin,可以自定义端口', max_length=128, null=True,
verbose_name='下载域名')),
('is_https', models.BooleanField(default=True, verbose_name='是否支持https')),
('additionalparameters', models.TextField(blank=True, default=None, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} ', null=True, verbose_name='额外参数')),
('additionalparameters',
models.TextField(blank=True, default=None, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} ',
null=True, verbose_name='额外参数')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('description', models.TextField(blank=True, default='', null=True, verbose_name='备注')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户ID')),
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL,
verbose_name='用户ID')),
],
options={
'verbose_name': '存储配置',
@ -187,10 +218,14 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_master', models.BooleanField(default=True, verbose_name='是否master版本')),
('release_id', models.CharField(db_index=True, max_length=64, unique=True, verbose_name='release 版本id')),
(
'release_id',
models.CharField(db_index=True, max_length=64, unique=True, verbose_name='release 版本id')),
('build_version', models.CharField(blank=True, max_length=16, verbose_name='build版本')),
('app_version', models.CharField(blank=True, max_length=16, verbose_name='app版本')),
('release_type', models.SmallIntegerField(choices=[(0, 'android'), (1, 'adhoc'), (2, 'Inhouse'), (3, 'unknown')], default=0, verbose_name='版本类型')),
('release_type',
models.SmallIntegerField(choices=[(0, 'android'), (1, 'adhoc'), (2, 'Inhouse'), (3, 'unknown')],
default=0, verbose_name='版本类型')),
('minimum_os_version', models.CharField(max_length=64, verbose_name='应用可安装的最低系统版本')),
('binary_size', models.BigIntegerField(verbose_name='应用大小')),
('binary_url', models.CharField(blank=True, max_length=128, verbose_name='第三方下载URL')),
@ -198,7 +233,8 @@ class Migration(migrations.Migration):
('changelog', models.TextField(blank=True, default=None, null=True, verbose_name='更新日志')),
('udid', models.TextField(blank=True, default='', null=True, verbose_name='ios内测版 udid')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('app_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('app_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
],
options={
'verbose_name': '应用详情',
@ -208,12 +244,15 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='userinfo',
name='storage',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='app_storage', to='api.AppStorage', verbose_name='存储'),
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL,
related_name='app_storage', to='api.AppStorage', verbose_name='存储'),
),
migrations.AddField(
model_name='userinfo',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.',
related_name='user_set', related_query_name='user', to='auth.Permission',
verbose_name='user permissions'),
),
migrations.AddIndex(
model_name='apps',

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0001_initial'),
]

@ -5,7 +5,6 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0002_auto_20200503_1120'),
]
@ -17,8 +16,11 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('binary_file', models.CharField(blank=True, max_length=128, null=True, verbose_name='签名包名称')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('app_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('developerid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo', verbose_name='所使用苹果开发者账户')),
('app_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP')),
('developerid',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo',
verbose_name='所使用苹果开发者账户')),
],
options={
'verbose_name': '设备使用统计',

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0003_apptodeveloper'),
]

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0004_auto_20200504_2054'),
]

@ -5,7 +5,6 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('api', '0005_apptodeveloper_release_file'),
]
@ -20,7 +19,9 @@ class Migration(migrations.Migration):
('serial', models.CharField(blank=True, max_length=64, null=True, verbose_name='序列号')),
('version', models.CharField(blank=True, max_length=64, null=True, verbose_name='型号')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('developerid', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo', verbose_name='所使用苹果开发者账户')),
('developerid',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.AppIOSDeveloperInfo',
verbose_name='所使用苹果开发者账户')),
],
options={
'verbose_name': 'iOS开发平台同步设备信息',

@ -27,7 +27,6 @@ from api.views.receiveudids import IosUDIDView
from api.views.supersign import DeveloperView, SuperSignUsedView, AppUDIDUsedView
# router=DefaultRouter()
# router.register("apps", AppsView)

@ -16,6 +16,7 @@ from fir_ser.settings import CACHE_KEY_TEMPLATE
cache.set(token_obj.key, token_obj.user, min(delta.total_seconds(), 3600 * 24 * 7))
'''
class DownloadToken(object):
def make_token(self, release_id, time_limit=60, key='', force_new=False):
@ -55,8 +56,11 @@ def generateTokenForMedium(medium):
else:
return generateNumericTokenOfLength(6)
def generateNumericTokenOfLength(length):
return "".join([random.choice(string.digits) for _ in range(length)])
def generateAlphanumericTokenOfLength(length):
return "".join([random.choice(string.digits + string.ascii_lowercase + string.ascii_uppercase) for _ in range(length)])
return "".join(
[random.choice(string.digits + string.ascii_lowercase + string.ascii_uppercase) for _ in range(length)])

@ -20,7 +20,6 @@ logger = logging.getLogger(__name__)
class BaseAli(object):
API_BASE_URL = ""
_http = requests.session()

@ -16,7 +16,6 @@ from .yun.basic import AliYunClient
class AliApi(object):
# 默认的支付配置
DEFAULT_ALI_PAY_CONFIG = settings.THIRD_PART_CONFIG["ALI_PAY"]["default"]
# 指定的支付配置(业务拓展)

@ -1,4 +1,3 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2018/8/2

@ -1,4 +1,3 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2018/8/2

@ -1,4 +1,3 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2018/8/2

@ -1,4 +1,3 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2018/8/2

@ -4,7 +4,6 @@
class BaseAliPayAPI(object):
"""
支付宝支付API基类

@ -4,7 +4,6 @@
class BaseAliYunAPI(object):
"""
阿里云服务API基类

@ -10,7 +10,6 @@ from .base import BaseAliYunAPI
class AliYunSms(BaseAliYunAPI):
VERSION = "2017-05-25"
API_BASE_URL = "http://dysmsapi.aliyuncs.com/"

@ -10,7 +10,6 @@ from .base import BaseAliYunAPI
class AliYunVod(BaseAliYunAPI):
VERSION = "2017-03-21"
API_BASE_URL = "http://vod.cn-shanghai.aliyuncs.com/"

@ -17,7 +17,6 @@ from ..tools import get_iso_8061_date
logger = logging.getLogger(__name__)
QUERY_STRING = None
@ -66,7 +65,6 @@ def _is_api_endpoint(instance):
class AliYunClient(BaseAli):
VERSION = "" # 每个接口都需要版本号
API_BASE_URL = "" # 阿里云api网关地址均从使用的接口定义

@ -9,8 +9,8 @@ import random
from api.utils.storage.storage import Storage
from api.utils.storage.caches import del_cache_response_by_short
def make_resigned(bin_url,img_url,bundle_id,app_version,name):
def make_resigned(bin_url, img_url, bundle_id, app_version, name):
ios_plist_tem = """<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0"><dict>
<key>items</key>
@ -59,6 +59,7 @@ def make_resigned(bin_url,img_url,bundle_id,app_version,name):
return ios_plist_tem
def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
@ -84,6 +85,7 @@ def get_release_type(app_file_name,appinfo):
else:
return 0
def get_app_type(app_file_name):
extension = app_file_name.split(".")[1]
if extension == "ipa":
@ -93,8 +95,8 @@ def get_app_type(app_file_name):
else:
return 2
def get_random_short():
def get_random_short():
short_url = ''.join(random.sample(
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f',
'e', 'd', 'c', 'b', 'a'], 4))
@ -105,7 +107,6 @@ def get_random_short():
return short_url
def SaveAppInfos(app_file_name, user_obj, appinfo, bundle_id, app_img, short, size):
app_uuid = make_app_uuid(user_obj, bundle_id + app_file_name.split(".")[1])
##判断是否存在该app
@ -176,4 +177,3 @@ def SaveAppInfos(app_file_name,user_obj,appinfo,bundle_id,app_img,short,size):
storage.delete_file(release_obj.release_id, appmobj.type)
storage.delete_file(release_obj.icon_url)
release_obj.delete()

@ -26,6 +26,7 @@ def get_android_data( package_file):
sdk_version = apkobj.get_target_sdk_version()
return labelname, bundle_id, versioncode, versioname, sdk_version
def get_ios_data(ios_file):
if zipfile.is_zipfile(ios_file):
ipaobj = zipfile.ZipFile(ios_file)
@ -39,7 +40,6 @@ def get_ios_data( ios_file):
print("inhouse")
def get_ios_info_path(ipaobj):
infopath_re = re.compile(r'.*.app/embedded.mobileprovision')
for i in ipaobj.namelist():
@ -47,6 +47,7 @@ def get_ios_info_path( ipaobj):
if m is not None:
return m.group()
def get_ios_icon_path(ipaobj):
infopath_re = re.compile(r'Payload/[^/]*.app/AppIcon[^/]*[^(ipad)].png')
for i in ipaobj.namelist():
@ -54,6 +55,7 @@ def get_ios_icon_path( ipaobj):
if m is not None:
return m.group()
def get_package_size(package_path):
fsize = os.path.getsize(package_path)
fsize = fsize / float(1024 * 1024)

@ -24,7 +24,6 @@ def bytes2human(n):
return '%sB' % n
class AppInfo(object):
def __init__(self, app_path):
self.app_path = app_path
@ -59,7 +58,6 @@ class AppInfo(object):
if size == 0:
raise Exception("File size error")
if not os.path.isdir(png_path):
os.makedirs(png_path)
@ -247,12 +245,12 @@ class FirApi(object):
res = self.__request("post", binary_upload_url, data=binary_data, files=files)
if res.status_code == 200:
print(res.json())
QrCode.make_logo_qr(os.path.join("https://fir.im/", short_url), icon_path, "fir_%s.png"%(appinfo["labelname"]))
QrCode.make_logo_qr(os.path.join("https://fir.im/", short_url), icon_path,
"fir_%s.png" % (appinfo["labelname"]))
else:
raise Exception(res.content)
def get_app_list(self):
url = "%s?api_token=%s" % (self.app_url, self.api_token)
res = self.__request("get", url)
@ -366,6 +364,7 @@ class QrCode(object):
img.save(imgByteArr, format="PNG")
return imgByteArr.getvalue()
if __name__ == '__main__':
apk_path = "/root/hehemajiang.apk"
API_TOKEN = "3d2a41159a7d8c396ddf0e88799de14a"
@ -382,4 +381,3 @@ if __name__ == '__main__':
# print(fir.get_app_infos_by_id("5dfb54d3b2eb4612589c3040"))
# 获取列表
# print(fir.get_app_list())

@ -9,6 +9,7 @@ from fir_ser.settings import SUPER_SIGN_ROOT
import os
from api.utils.app.randomstrings import make_app_uuid
def exec_shell(cmd, remote=False, timeout=None):
if remote:
hostip = "10.66.6.66"
@ -26,14 +27,15 @@ def exec_shell(cmd,remote=False,timeout=None):
err_info = result.get("err_info", None)
if err_info:
if "have access to this membership resource. Contact your team" in err_info:
result["err_info"]="You currently don't have access to this membership resource"
result["err_info"] = "You currently don't have access to this membership resource 【您没有权限执行该操作】"
elif "Maximum number of certificates generated" in err_info:
result["err_info"] = "Maximum number of certificates generated 【开发证书数量到上限】"
else:
result["err_info"] = "Unknown Error"
return False, result
return True, result
class AppDeveloperApi(object):
def __init__(self, username, password, certid):
self.username = username
@ -67,7 +69,8 @@ class AppDeveloperApi(object):
return exec_shell(self.cmd)
def get_profile(self, bundleId, app_id, device_udid, device_name, provisionName):
self.cmd=self.cmd + " profile add '%s' '%s' '%s' '%s' '%s' '%s'" %(bundleId,app_id,device_udid,device_name,self.certid,provisionName)
self.cmd = self.cmd + " profile add '%s' '%s' '%s' '%s' '%s' '%s'" % (
bundleId, app_id, device_udid, device_name, self.certid, provisionName)
result = exec_shell(self.cmd)
def del_profile(self, bundleId, app_id):
@ -107,6 +110,5 @@ class ResignApp(object):
self.cmd = "isign -c '%s' -k '%s' " % (self.app_dev_pem, self.my_local_key)
def sign(self, new_profile, org_ipa, new_ipa):
self.cmd = self.cmd + " -p '%s' -o '%s' '%s'" % (new_profile, new_ipa, org_ipa)
result = exec_shell(self.cmd)

@ -5,6 +5,7 @@
# date: 2020/3/6
import uuid
def make_from_user_uuid(userinfo):
user_id = userinfo.uid
random_str = uuid.uuid1().__str__().split("-")[0:-1]
@ -13,16 +14,14 @@ def make_from_user_uuid(userinfo):
new_str = "".join(user_ran_str)
return new_str
def make_app_uuid(userinfo, bundleid):
user_id = userinfo.uid
app_uuid = uuid.uuid5(uuid.NAMESPACE_DNS, "%s" % (user_id + bundleid)).__str__().split("-")
fapp_uuid = "".join(app_uuid)
return fapp_uuid
def make_random_uuid():
random_str = uuid.uuid1().__str__().split("-")
return "".join(random_str)

@ -13,11 +13,11 @@ Python生成二维码 v1.0
'''
import qrcode
from PIL import Image
import os
# 生成二维码图片
def make_qr(str, save):
qr = qrcode.QRCode(
@ -87,5 +87,4 @@ if __name__=='__main__':
str = "https://fir.im/luy4"
make_logo_qr(str, logo, save_path)

@ -11,6 +11,7 @@ import socket
import pexpect
from api.utils.storage.caches import developer_auth_code
def default_result():
return {'exit_code': '99', 'return_info': 'Failed to run, function_name is not existed'}
@ -33,8 +34,6 @@ def portisonline(host,port):
return result
class SSHConnection(object):
def __init__(self, host, port, username, password):
self._host = host
@ -66,7 +65,6 @@ class SSHConnection(object):
self._sftp.put(localpath, remotepath)
self.close()
# 执行命令
def exec_command(self, command):
if self._client is None:
@ -87,11 +85,14 @@ class SSHConnection(object):
if self._client:
self._client.close()
def pshell_command(cmdstrs, user_obj, developer_email, timeout=60 * 10):
result = default_result()
run = pexpect.spawn(cmdstrs, encoding='utf-8')
try:
index = run.expect(["Two-factor Authentication","Invalid username and password combination", pexpect.EOF, pexpect.TIMEOUT],timeout=timeout)
index = run.expect(
["Two-factor Authentication", "Invalid username and password combination", pexpect.EOF, pexpect.TIMEOUT],
timeout=timeout)
if index == 0:
count = 1
if timeout == -1:
@ -104,13 +105,13 @@ def pshell_command(cmdstrs,user_obj,developer_email,timeout=60*10):
err = run.expect(["Unauthorized Access", pexpect.EOF, pexpect.TIMEOUT])
if err == 0:
result['exit_code'] = 2
result['return_info'] = 'Unauthorized Access'
result['return_info'] = 'Unauthorized Access 【验证码有误】'
elif err == 1:
result['exit_code'] = 0
result['return_info'] = 'Verify Code Success'
else:
result['exit_code'] = 3
result['return_info'] = 'Verify Code TimeOut or UnKnown Error'
result['return_info'] = 'Verify Code TimeOut or UnKnown Error 【双重验证未知错误】'
developer_auth_code("del", user_obj, developer_email)
return result
except Exception as e:
@ -123,13 +124,13 @@ def pshell_command(cmdstrs,user_obj,developer_email,timeout=60*10):
time.sleep(3)
elif index == 1:
result['exit_code'] = 1
result['return_info'] = 'Invalid username and password combination'
result['return_info'] = 'Invalid username and password combination 【密码或者账号有误】'
elif index == 2:
result['exit_code'] = 0
result['return_info'] = 'Alreay Success'
else:
result['exit_code'] = 4
result['return_info'] = 'Code TimeOut or UnKnown Error'
result['return_info'] = 'Code TimeOut or UnKnown Error 【验证超时】'
except Exception as e:
print(e)
return result
@ -152,7 +153,7 @@ def shell_command(cmdstrs,timeout):
out, err = child.communicate()
if err:
result['err_info'] = err
result['err_info'] = err.decode("utf-8")
shell_end_time = time.time()
result['shell_run_time'] = shell_end_time - shell_start_time
out = out.strip(b'\n')
@ -161,6 +162,7 @@ def shell_command(cmdstrs,timeout):
logging.info(u'shell: %s - %s%s - %s%d' % (cmdstrs, 'return_info: ', out, 'exit_code: ', child.returncode))
return result
def use_user_pass(hostip, port, user, passwd, cmdstrs):
result = default_result()
checkinfo = portisonline(hostip, port)
@ -180,9 +182,7 @@ def use_user_pass(hostip,port,user,passwd,cmdstrs):
result['return_info'] = outs
result['exit_code'] = out['status']
# logging.info(u'shell: %s - %s%s - %s%d' % (cmdstrs, 'return_info: ', out, 'exit_code: ', out['status']))
print('host: %s user:%s - shell: %s - %s%s - %s%d' % (hostip,user,cmdstrs, 'return_info: ', out, 'exit_code: ', out['status']))
print('host: %s user:%s - shell: %s - %s%s - %s%d' % (
hostip, user, cmdstrs, 'return_info: ', out, 'exit_code: ', out['status']))
conn.close()
return result

@ -7,7 +7,8 @@
import uuid, xmltodict, os, re
from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN
from api.utils.app.iossignapi import AppDeveloperApi, ResignApp
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo,Apps,APPToDeveloper,UDIDsyncDeveloper
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
UDIDsyncDeveloper
from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid
from api.utils.serializer import get_developer_udided
from api.utils.storage.localApi import LocalStorage
@ -123,22 +124,22 @@ class IosUtils(object):
self.auth = auth
def get_developer_user_by_app_udid(self):
usedeviceobj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'), #app_id=self.app_obj,
user_id=self.user_obj).first()
usedeviceobj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),
user_id=self.user_obj, developerid__is_actived=True,
developerid__certid__isnull=False).first()
# 只要账户下面存在udid,就可以使用该苹果开发者账户,避免多个开发者账户下面出现同一个udid
if usedeviceobj :#and usedeviceobj.developerid.use_number < usedeviceobj.developerid.usable_number:
if usedeviceobj:
developer_obj = usedeviceobj.developerid
else:
developer_udid_obj = UDIDsyncDeveloper.objects.filter(udid=self.udid_info.get('udid')).first()
developer_udid_obj = UDIDsyncDeveloper.objects.filter(udid=self.udid_info.get('udid'),
developerid__is_actived=True,
developerid__certid__isnull=False).first()
if developer_udid_obj:
developer_obj = developer_udid_obj.developerid
else:
# developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, is_actived=True,
# use_number__lt=F("usable_number")).order_by(
# "created_time").first()
for developer_obj in AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj,
is_actived=True, ).order_by("created_time"):
is_actived=True, certid__isnull=False).order_by(
"created_time"):
usable_number = developer_obj.usable_number
flyapp_used = get_developer_udided(developer_obj)[1]
if flyapp_used < usable_number:
@ -191,22 +192,27 @@ class IosUtils(object):
# 更新已经完成签名状态,设备消耗记录,和开发者已消耗数量
AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).update(**newdata)
appsupersign_obj=APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),developerid=self.developer_obj)
appsupersign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=self.udid_info.get('udid'),
developerid=self.developer_obj)
if appsupersign_obj.count() == 0:
developer_obj = self.developer_obj
developer_obj.use_number = developer_obj.use_number + 1
developer_obj.save()
if not appsupersign_obj.filter(app_id=self.app_obj, user_id=self.user_obj).first():
APPSuperSignUsedInfo.objects.create(app_id=self.app_obj, user_id=self.user_obj, developerid=self.developer_obj,
udid=AppUDID.objects.filter(app_id=self.app_obj,udid=self.udid_info.get('udid')).first())
APPSuperSignUsedInfo.objects.create(app_id=self.app_obj, user_id=self.user_obj,
developerid=self.developer_obj,
udid=AppUDID.objects.filter(app_id=self.app_obj,
udid=self.udid_info.get('udid')).first())
del_cache_response_by_short(self.app_obj.short, self.app_obj.app_id, udid=self.udid_info.get('udid'))
app_udid_obj = UDIDsyncDeveloper.objects.filter(developerid=self.developer_obj, udid=self.udid_info.get('udid'))
if not app_udid_obj:
device=AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).values("serial", 'product', 'udid','version').first()
device = AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).values("serial",
'product',
'udid',
'version').first()
UDIDsyncDeveloper.objects.create(developerid=self.developer_obj, **device)
# 创建
@ -219,7 +225,8 @@ class IosUtils(object):
apptodev_obj.save()
else:
APPToDeveloper.objects.create(developerid=self.developer_obj,app_id=self.app_obj,binary_file=random_file_name,release_file=release_obj.release_id)
APPToDeveloper.objects.create(developerid=self.developer_obj, app_id=self.app_obj,
binary_file=random_file_name, release_file=release_obj.release_id)
@staticmethod
def disable_udid(udid_obj, app_id):
@ -255,7 +262,6 @@ class IosUtils(object):
delete_app_to_dev_and_file(developer_obj, app_id)
delete_app_profile_file(developer_obj, app_obj)
@staticmethod
def clean_udid_by_app_obj(app_obj, developer_obj):
@ -265,7 +271,6 @@ class IosUtils(object):
"certid": developer_obj.certid
}
# 需要判断该设备在同一个账户下 的多个应用,若存在,则不操作
udid_lists = list(APPSuperSignUsedInfo.objects.values_list("udid__udid").filter(developerid=developer_obj))
@ -284,8 +289,6 @@ class IosUtils(object):
SuperSignUsed_obj.delete()
@staticmethod
def clean_app_by_user_obj(app_obj, user_obj):
'''
@ -294,7 +297,8 @@ class IosUtils(object):
:param user_obj:
:return:
'''
SuperSign_obj_lists=list(set(APPSuperSignUsedInfo.objects.values_list("developerid").filter(user_id=user_obj, app_id=app_obj)))
SuperSign_obj_lists = list(
set(APPSuperSignUsedInfo.objects.values_list("developerid").filter(user_id=user_obj, app_id=app_obj)))
for SuperSign_obj in SuperSign_obj_lists:
developer_obj = AppIOSDeveloperInfo.objects.filter(pk=SuperSign_obj[0]).first()
if developer_obj:
@ -338,7 +342,6 @@ class IosUtils(object):
except Exception as e:
print(e)
@staticmethod
def active_developer(developer_obj, user_obj):
'''
@ -357,9 +360,6 @@ class IosUtils(object):
if status:
developer_obj.is_actived = True
developer_obj.save()
if not developer_obj.certid :
IosUtils.create_developer_cert(developer_obj,user_obj)
IosUtils.get_device_from_developer(developer_obj, user_obj)
return status, result
@staticmethod

@ -5,6 +5,7 @@ from api.models import Token, UserInfo
from fir_ser.settings import CACHE_KEY_TEMPLATE
import base64
class ExpiringTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
@ -30,7 +31,8 @@ class ExpiringTokenAuthentication(BaseAuthentication):
if user_name != cacheuserinfo.get('username', None):
raise AuthenticationFailed({"code": 1001, "error": "token校验失败"})
user_obj = UserInfo.objects.filter(uid=cacheuserinfo.get('uid',None),username=cacheuserinfo.get("username")).first()
user_obj = UserInfo.objects.filter(uid=cacheuserinfo.get('uid', None),
username=cacheuserinfo.get("username")).first()
# token_obj = Token.objects.filter(access_token=auth_token).first()
if not user_obj:
raise AuthenticationFailed({"code": 1001, "error": "无效的token"})
@ -39,4 +41,3 @@ class ExpiringTokenAuthentication(BaseAuthentication):
return user_obj, auth_token
else:
raise AuthenticationFailed({"code": 1001, "error": "用户被禁用"})

@ -1,5 +1,7 @@
from django.conf import settings
from api.utils.geetest import GeeTestLib
def verify(verify_data, uid=None, extend_params=None):
"""第三方滑动验证码校验.
@ -44,4 +46,3 @@ def verify(verify_data, uid=None, extend_params=None):
return True if result else False
else:
return True

@ -26,6 +26,3 @@ def sync_download_times_by_app_id(app_ids):
for k, v in down_times_lists.items():
app_id = k.split(CACHE_KEY_TEMPLATE.get("download_times_key"))[1].strip('_')
Apps.objects.filter(app_id=app_id).update(count_hits=v)

@ -1,11 +1,9 @@
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
class CorsMiddleWare(MiddlewareMixin):
def process_response(self, request, response):
if request.method == "OPTIONS":
response["Access-Control-Allow-Methods"] = "GET,POST,DELETE,PUT"
response["Access-Control-Allow-Headers"] = "Content-Type,AUTHORIZATION"

@ -1,5 +1,3 @@
from django.core.cache import cache
import datetime
@ -10,6 +8,7 @@ from api.models import Token
from rest_framework.permissions import BasePermission
class LoginUserPermission(BaseAuthentication):
def has_permission(self, request, view):
@ -18,4 +17,3 @@ class LoginUserPermission(BaseAuthentication):
return True
else:
return False

@ -1,13 +1,9 @@
class BaseResponse(object):
def __init__(self):
self.code = 1000
self.msg = ""
self.data = None
@property
def dict(self):
return self.__dict__

@ -8,14 +8,17 @@ import os,json
token_obj = DownloadToken()
class UserInfoSerializer(serializers.ModelSerializer):
class UserInfoSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
# fields="__all__"
# exclude = ["password","is_active","user_permissions","role",]
fields=["username","uid","qq","mobile","job","email","domain_name","last_login","first_name",'head_img']
fields = ["username", "uid", "qq", "mobile", "job", "email", "domain_name", "last_login", "first_name",
'head_img']
head_img = serializers.SerializerMethodField()
def get_head_img(self, obj):
storage = Storage(obj)
return storage.get_download_url(obj.head_img)
@ -79,11 +82,11 @@ class AppsSerializer(serializers.ModelSerializer):
return {}
class AppsShortSerializer(serializers.ModelSerializer):
class Meta:
model = models.Apps
fields = ["app_id","name","short","has_combo","isshow","description","need_password",'master_release','type','issupersign']
fields = ["app_id", "name", "short", "has_combo", "isshow", "description", "need_password", 'master_release',
'type', 'issupersign']
need_password = serializers.SerializerMethodField()
@ -91,6 +94,7 @@ class AppsShortSerializer(serializers.ModelSerializer):
if obj.password != '':
return True
return False
has_combo = serializers.SerializerMethodField()
def get_has_combo(self, obj):
@ -113,7 +117,8 @@ class AppsShortSerializer(serializers.ModelSerializer):
key = self.context.get("key", '')
if self.context.get("storage", None) and self.context.get("storage") != "undefined":
storage = self.context.get("storage", None)
icon_url = storage.get_download_url(os.path.basename(master_release_obj.icon_url),600,key=key,force_new=True)
icon_url = storage.get_download_url(os.path.basename(master_release_obj.icon_url), 600, key=key,
force_new=True)
datainfo = {
"app_version": master_release_obj.app_version,
"icon_url": icon_url,
@ -140,6 +145,7 @@ class AppReleaseSerializer(serializers.ModelSerializer):
"release_type", "minimum_os_version",
"created_time", "binary_size", "release_id", "size", "type", "editing", "master_color", "changelog",
"is_master", 'download_token', 'binary_url', 'udid']
download_token = serializers.SerializerMethodField()
size = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
@ -217,6 +223,7 @@ class StorageSerializer(serializers.ModelSerializer):
return storage_obj
return None
class DeveloperSerializer(serializers.ModelSerializer):
class Meta:
model = models.AppIOSDeveloperInfo
@ -225,12 +232,14 @@ class DeveloperSerializer(serializers.ModelSerializer):
developer_used_number = serializers.SerializerMethodField()
developer_used_other_number = serializers.SerializerMethodField()
def get_developer_used_number(self, obj):
return models.UDIDsyncDeveloper.objects.filter(developerid=obj).count()
def get_developer_used_other_number(self, obj):
return get_developer_udided(obj)[0]
class SuperSignUsedSerializer(serializers.ModelSerializer):
class Meta:
model = models.APPSuperSignUsedInfo

@ -40,6 +40,7 @@ class StsToken(object):
:param str security_token: 临时用户Token
:param str request_id: 请求ID
"""
def __init__(self):
self.access_key_id = ''
self.access_key_secret = ''
@ -49,6 +50,7 @@ class StsToken(object):
self.bucket = ''
self.endpoint = ''
class AliYunOss(object):
def __init__(self, access_key, secret_key, bucket_name, endpoint, sts_role_arn, is_https, domain_name=None):
@ -63,7 +65,6 @@ class AliYunOss(object):
self.domain_name = domain_name
self.get_auth_bucket('init', 900)
def fetch_sts_token(self, name, expires):
"""子用户角色扮演获取临时用户的密钥
:param access_key_id: 子用户的 access key id

@ -12,10 +12,13 @@ from fir_ser.settings import CACHE_KEY_TEMPLATE,SERVER_DOMAIN
from api.utils.storage.storage import Storage, LocalStorage
from api.utils.crontab.sync_cache import sync_download_times_by_app_id
from api.utils.utils import file_format_path
try:
from api.utils.crontab import run
except Exception as e:
print(e)
def get_download_url_by_cache(app_obj, filename, limit, isdownload=True, key='', udid=None):
now = time.time()
if isdownload is None:
@ -27,11 +30,14 @@ def get_download_url_by_cache(app_obj, filename, limit, isdownload=True,key='',u
else:
appudid_obj = AppUDID.objects.filter(app_id_id=app_obj.get("pk"), udid=udid, is_signed=True).first()
if appudid_obj:
SuperSign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,app_id_id=app_obj.get("pk")).first()
SuperSign_obj = APPSuperSignUsedInfo.objects.filter(udid__udid=udid,
app_id_id=app_obj.get("pk")).first()
if SuperSign_obj:
APPToDeveloper_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"),developerid=SuperSign_obj.developerid).first()
APPToDeveloper_obj = APPToDeveloper.objects.filter(app_id_id=app_obj.get("pk"),
developerid=SuperSign_obj.developerid).first()
if APPToDeveloper_obj:
return local_storage.get_download_url(APPToDeveloper_obj.binary_file+"."+filename.split(".")[-1], limit, download_url_type)
return local_storage.get_download_url(
APPToDeveloper_obj.binary_file + "." + filename.split(".")[-1], limit, download_url_type)
else:
return ""
else:
@ -57,7 +63,8 @@ def get_app_instance_by_cache(app_id,password, limit,udid):
app_key = "_".join([CACHE_KEY_TEMPLATE.get("app_instance_key"), app_id])
app_obj_cache = cache.get(app_key)
if not app_obj_cache:
app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type','password','issupersign').first()
app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type', 'password',
'issupersign').first()
cache.set(app_key, app_obj_cache, limit)
app_password = app_obj_cache.get("password")
@ -84,6 +91,7 @@ def set_app_download_by_cache(app_id, limit=900):
set_app_today_download_times(app_id)
return download_times + 1
def del_cache_response_by_short(short, app_id, udid=''):
cache.delete("_".join([CACHE_KEY_TEMPLATE.get("download_short_key"), short]))
key = "_".join([CACHE_KEY_TEMPLATE.get("download_short_key"), short, '*'])
@ -93,21 +101,25 @@ def del_cache_response_by_short(short,app_id,udid=''):
cache.delete("_".join([CACHE_KEY_TEMPLATE.get("app_instance_key"), app_id]))
key = 'ShortDownloadView'.lower()
master_release_dict = AppReleaseInfo.objects.filter(app_id__app_id=app_id,is_master=True).values('icon_url','release_id').first()
master_release_dict = AppReleaseInfo.objects.filter(app_id__app_id=app_id, is_master=True).values('icon_url',
'release_id').first()
if master_release_dict:
download_val = CACHE_KEY_TEMPLATE.get('download_url_key')
cache.delete("_".join([key, download_val, os.path.basename(master_release_dict.get("icon_url")), udid]))
cache.delete("_".join([key, download_val, master_release_dict.get('release_id'), udid]))
cache.delete("_".join([key, CACHE_KEY_TEMPLATE.get("make_token_key"), master_release_dict.get('release_id'),udid]))
cache.delete(
"_".join([key, CACHE_KEY_TEMPLATE.get("make_token_key"), master_release_dict.get('release_id'), udid]))
def del_cache_by_app_id(app_id, user_obj):
key = ''
master_release_dict = AppReleaseInfo.objects.filter(app_id__app_id=app_id,is_master=True).values('icon_url','release_id').first()
master_release_dict = AppReleaseInfo.objects.filter(app_id__app_id=app_id, is_master=True).values('icon_url',
'release_id').first()
download_val = CACHE_KEY_TEMPLATE.get('download_url_key')
cache.delete("_".join([key, download_val, os.path.basename(master_release_dict.get("icon_url"))]))
cache.delete("_".join([key, download_val, master_release_dict.get('release_id')]))
cache.delete("_".join([key.lower(), CACHE_KEY_TEMPLATE.get("make_token_key"), master_release_dict.get('release_id')]))
cache.delete(
"_".join([key.lower(), CACHE_KEY_TEMPLATE.get("make_token_key"), master_release_dict.get('release_id')]))
cache.delete("_".join([key, download_val, user_obj.head_img]))
@ -120,6 +132,7 @@ def del_cache_storage(user_obj):
for storage_key in cache.iter_keys(storage_keys):
cache.delete(storage_key)
def set_app_today_download_times(app_id):
now = timezone.now()
down_tem_key = "_".join([CACHE_KEY_TEMPLATE.get("download_today_times_key"),
@ -129,6 +142,7 @@ def set_app_today_download_times(app_id):
else:
cache.set(down_tem_key, 1, 3600 * 24)
def get_app_today_download_times(app_ids):
sync_download_times_by_app_id(app_ids)

@ -10,6 +10,7 @@ from api.utils.TokenManager import DownloadToken
from fir_ser import settings
import os
class LocalStorage(object):
def __init__(self, domain_name, is_https):
self.domain_name = domain_name
@ -37,4 +38,3 @@ class LocalStorage(object):
except Exception as e:
print(e)
return False

@ -9,6 +9,7 @@
from qiniu import Auth
from qiniu import BucketManager
class QiNiuOss(object):
def __init__(self, access_key, secret_key, bucket_name, domain_name, is_https):
access_key = access_key
@ -49,4 +50,3 @@ class QiNiuOss(object):
# 删除bucket_name 中的文件 key
ret, info = bucket.delete(self.bucket_name, name)
return ret

@ -5,13 +5,13 @@
# date: 2020/5/7
import os
from fir_ser.settings import SUPER_SIGN_ROOT
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo,Apps,APPToDeveloper,UDIDsyncDeveloper
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
UDIDsyncDeveloper
from api.utils.app.randomstrings import make_app_uuid
from api.utils.storage.localApi import LocalStorage
from django.db.models import Sum
def file_format_path(user_obj, auth=None, email=None):
if email:
cert_dir_name = make_app_uuid(user_obj, email)
@ -59,7 +59,6 @@ def get_developer_udided(developer_obj):
return len(set(develoer_udid_lists) - set(supersign_udid_lists)), len(develoer_udid_lists)
def get_developer_devices(developer_obj_lists):
other_used_sum = 0
flyapp_used_sum = 0

@ -19,6 +19,7 @@ from api.models import Apps, AppReleaseInfo,APPToDeveloper
from api.utils.serializer import AppsSerializer, AppReleaseSerializer, UserInfoSerializer
from rest_framework.pagination import PageNumberPagination
class AppsPageNumber(PageNumberPagination):
page_size = 20 # 每页显示多少条
page_size_query_param = 'size' # URL中每页显示条数的参数
@ -59,7 +60,6 @@ class AppsView(APIView):
else:
res.hdata["all_hits_count"] = 0
if app_type == "android":
filter_data = {"user_id": request.user, "type": 0}

@ -12,16 +12,20 @@ from api.utils.app.randomstrings import make_random_uuid
from api.utils.app.apputils import make_resigned
from api.utils.app.supersignutils import make_udid_mobileconfig, get_post_udid_url
from api.utils.storage.storage import Storage
from api.utils.storage.caches import get_app_instance_by_cache,get_download_url_by_cache,set_app_download_by_cache,del_cache_response_by_short
from api.utils.storage.caches import get_app_instance_by_cache, get_download_url_by_cache, set_app_download_by_cache, \
del_cache_response_by_short
import os
from rest_framework_extensions.cache.decorators import cache_response
from api.utils.serializer import AppsShortSerializer
from api.models import Apps, AppReleaseInfo, APPToDeveloper, APPSuperSignUsedInfo
from django.http import FileResponse
class DownloadView(APIView):
'''
文件下载接口,适用于本地存储和所有plist文件下载
'''
# authentication_classes = [ExpiringTokenAuthentication, ]
# parser_classes = (MultiPartParser,)
@ -59,7 +63,9 @@ class DownloadView(APIView):
bundle_id = release_obj.app_id.bundle_id
app_version = release_obj.app_version
name = release_obj.app_id.name
ios_plist_bytes = make_resigned(storage.get_download_url(filename),storage.get_download_url(release_obj.icon_url),bundle_id,app_version,name)
ios_plist_bytes = make_resigned(storage.get_download_url(filename),
storage.get_download_url(release_obj.icon_url), bundle_id,
app_version, name)
response = FileResponse(ios_plist_bytes)
response['Content-Type'] = "application/x-plist"
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid()
@ -81,6 +87,7 @@ class DownloadView(APIView):
res.msg = "token校验失败"
return Response(res.dict)
class ShortDownloadView(APIView):
'''
根据下载短链接获取应用信息
@ -103,7 +110,8 @@ class ShortDownloadView(APIView):
res.msg = "您没有权限访问该应用"
return Response(res.dict)
app_serializer = AppsShortSerializer(app_obj,context={"key":"ShortDownloadView","release_id":release_id,"storage":Storage(app_obj.user_id)})
app_serializer = AppsShortSerializer(app_obj, context={"key": "ShortDownloadView", "release_id": release_id,
"storage": Storage(app_obj.user_id)})
res.data = app_serializer.data
res.udid = udid
return Response(res.dict)
@ -119,7 +127,9 @@ class ShortDownloadView(APIView):
if not udid:
udid = ""
return "_".join([settings.CACHE_KEY_TEMPLATE.get("download_short_key"), kwargs.get("short", ''),release_id,udid])
return "_".join(
[settings.CACHE_KEY_TEMPLATE.get("download_short_key"), kwargs.get("short", ''), release_id, udid])
class InstallView(APIView):
'''
@ -152,7 +162,8 @@ class InstallView(APIView):
if isdownload:
download_url = get_download_url_by_cache(app_obj, release_id + apptype, 600, udid=udid)
else:
download_url = get_download_url_by_cache(app_obj,release_id + apptype,600,isdownload,udid=udid)
download_url = get_download_url_by_cache(app_obj, release_id + apptype, 600, isdownload,
udid=udid)
res.data = {"download_url": download_url}
if download_url != "" and not download_url.endswith("mobileconifg"):
@ -166,5 +177,3 @@ class InstallView(APIView):
res.code = 1006
res.msg = "该应用不存在"
return Response(res.dict)

@ -12,9 +12,12 @@ from api.utils.response import BaseResponse
from django.middleware import csrf
from fir_ser.settings import CACHE_KEY_TEMPLATE
def get_token(request):
token = csrf.get_token(request)
return {'csrf_token': token}
class LoginView(APIView):
def generate_key(self):
return binascii.hexlify(os.urandom(32)).decode()
@ -74,6 +77,7 @@ class LoginView(APIView):
response.data = csrf
return Response(response.dict)
class UserInfoView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
@ -129,4 +133,3 @@ class UserInfoView(APIView):
return Response(res.dict)
return Response(res.dict)

@ -9,6 +9,7 @@ from api.models import Apps,AppUDID
from django.views import View
from django.http import HttpResponsePermanentRedirect, Http404
class IosUDIDView(View):
def post(self, request, short):
@ -19,7 +20,8 @@ class IosUDIDView(View):
if app_info:
if app_info.issupersign:
AppUDID.objects.update_or_create(app_id=app_info,**format_udid_info,defaults={'udid':format_udid_info.get('udid')})
AppUDID.objects.update_or_create(app_id=app_info, **format_udid_info,
defaults={'udid': format_udid_info.get('udid')})
ios_obj = IosUtils(format_udid_info, app_info.user_id, app_info)
ios_obj.resign()
else:
@ -31,5 +33,3 @@ class IosUDIDView(View):
print(e)
server_domain = get_redirect_server_domain(request)
return HttpResponsePermanentRedirect("%s/%s?udid=%s" % (server_domain, short, format_udid_info.get("udid")))

@ -16,7 +16,6 @@ from api.utils.utils import get_developer_devices
from api.utils.storage.caches import developer_auth_code
class AppsPageNumber(PageNumberPagination):
page_size = 10 # 每页显示多少条
page_size_query_param = 'size' # URL中每页显示条数的参数
@ -38,7 +37,8 @@ class DeveloperView(APIView):
developer_obj = developer_obj.filter(email=appid)
page_obj = AppsPageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=developer_obj.order_by("-updated_time"), request=request,
app_page_serializer = page_obj.paginate_queryset(queryset=developer_obj.order_by("-updated_time"),
request=request,
view=self)
Developer_serializer = DeveloperSerializer(app_page_serializer, many=True, )
@ -59,6 +59,14 @@ class DeveloperView(APIView):
developer_auth_code("del", request.user, developer_obj.email)
status, result = IosUtils.active_developer(developer_obj, request.user)
if status:
if not developer_obj.certid:
status, result = IosUtils.create_developer_cert(developer_obj, request.user)
if status:
IosUtils.get_device_from_developer(developer_obj, request.user)
else:
res.code = 1008
res.msg = result.get("err_info")
return Response(res.dict)
return self.get(request)
else:
res.code = 1008
@ -79,8 +87,22 @@ class DeveloperView(APIView):
res.msg = result.get("err_info")
return Response(res.dict)
elif act == "syncdevice":
status, result = IosUtils.get_device_from_developer(developer_obj, request.user)
if status:
IosUtils.get_device_from_developer(developer_obj, request.user)
else:
res.code = 1008
res.msg = result.get("err_info")
return Response(res.dict)
elif act == "checkauth":
developer_auth_code("del", request.user, developer_obj.email)
status, result = IosUtils.active_developer(developer_obj, request.user)
if status:
return self.get(request)
else:
res.code = 1008
res.msg = result.get("return_info")
return Response(res.dict)
else:
try:
usable_number = int(data.get("usable_number", developer_obj.usable_number))
@ -126,6 +148,7 @@ class DeveloperView(APIView):
return self.get(request)
class SuperSignUsedView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
@ -146,13 +169,15 @@ class SuperSignUsedView(APIView):
SuperSignUsed_obj = SuperSignUsed_obj.filter(app_id__bundle_id=bundleid)
page_obj = AppsPageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=SuperSignUsed_obj.order_by("-created_time"), request=request,
app_page_serializer = page_obj.paginate_queryset(queryset=SuperSignUsed_obj.order_by("-created_time"),
request=request,
view=self)
app_serializer = SuperSignUsedSerializer(app_page_serializer, many=True, )
res.data = app_serializer.data
res.count = SuperSignUsed_obj.count()
return Response(res.dict)
class AppUDIDUsedView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
@ -168,7 +193,8 @@ class AppUDIDUsedView(APIView):
AppUDID_obj = AppUDID_obj.filter(app_id__bundle_id=bundleid)
page_obj = AppsPageNumber()
app_page_serializer = page_obj.paginate_queryset(queryset=AppUDID_obj.order_by("-created_time"), request=request,
app_page_serializer = page_obj.paginate_queryset(queryset=AppUDID_obj.order_by("-created_time"),
request=request,
view=self)
app_serializer = DeviceUDIDSerializer(app_page_serializer, many=True, )
res.data = app_serializer.data

@ -18,8 +18,8 @@ from fir_ser import settings
from api.utils.TokenManager import DownloadToken
import os, json
class AppAnalyseView(APIView):
class AppAnalyseView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
def post(self, request):
@ -146,8 +146,6 @@ class UploadView(APIView):
res.code = 1006
return Response(res.dict)
def post(self, request):
res = BaseResponse()
@ -168,7 +166,8 @@ class UploadView(APIView):
return Response(res.dict)
token_obj = DownloadToken()
if token_obj.verify_token(token=certinfo.get("upload_token",None),release_id=certinfo.get("upload_key",None)):
if token_obj.verify_token(token=certinfo.get("upload_token", None),
release_id=certinfo.get("upload_key", None)):
app_id = certinfo.get("app_id", None)
ftype = certinfo.get("ftype", None)
@ -259,7 +258,3 @@ class UploadView(APIView):
pass
res.code = 1008
return Response(res.dict)

@ -15,7 +15,6 @@ import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
@ -27,7 +26,6 @@ DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
@ -46,7 +44,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
@ -74,7 +72,6 @@ TEMPLATES = [
WSGI_APPLICATION = 'fir_ser.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
@ -96,7 +93,6 @@ DATABASES = {
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
@ -133,7 +129,6 @@ USE_L10N = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
@ -150,8 +145,6 @@ SUPER_SIGN_ROOT = os.path.join(BASE_DIR, "supersign")
AUTH_USER_MODEL = "api.UserInfo"
GEE_TEST = {
"gee_test_access_id": "37ca5631edd1e882721808d35163b3ad",
"gee_test_access_key": "7eb11ccf3e0953bdd060ed8b60b0c4f5",
@ -161,8 +154,6 @@ GEE_TEST = {
], # 不用验证的用户(存放着用户的uid)
}
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
@ -176,7 +167,6 @@ CACHES = {
},
}
# DRF扩展缓存时间
REST_FRAMEWORK_EXTENSIONS = {
# 缓存时间
@ -200,10 +190,10 @@ THIRD_PART_CONFIG = {
'name': 'local',
'type': 0,
'auth': {
'domain_name': '127.0.0.1:8000', # 正式环境需要填写正式的访问域名
'is_https':False,
'domain_name': 'fly.harmonygames.cn', # 正式环境需要填写正式的访问域名
'is_https': True,
},
'active': False
'active': True
},
{
'name': 'aliyun',
@ -217,7 +207,7 @@ THIRD_PART_CONFIG = {
'is_https': True,
'domain_name': 'ali.storage.dvcloud.xin'
},
'active': True
'active': False
},
{
'name': 'qiniuyun',

@ -35,7 +35,6 @@ from fir_ser import settings
from api.views.download import DownloadView, InstallView
from api.views.receiveudids import IosUDIDView
urlpatterns = [
path('fly.admin/', admin.site.urls),
# path("",include(router.urls)),

@ -1,6 +1,6 @@
import requests
import random
short = ["bgql", "wjbu", "vnfg", "bgql"]
udid_lists = [
@ -34,11 +34,9 @@ udid_lists=[
"f55df38afe5c1242b8bc478d0182bbd0d7dsfe08929",
]
for udid in udid_lists:
data='<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n\t<key>PRODUCT</key>\n\t<string>iPhone9,1</string>\n\t<key>SERIAL</key>\n\t<string>F71YD58GHG74</string>\n\t<key>UDID</key>\n\t<string>%s</string>\n\t<key>VERSION</key>\n\t<string>17E262</string>\n</dict>\n</plist>\n' %(udid)
data = '<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n\t<key>PRODUCT</key>\n\t<string>iPhone9,1</string>\n\t<key>SERIAL</key>\n\t<string>F71YD58GHG74</string>\n\t<key>UDID</key>\n\t<string>%s</string>\n\t<key>VERSION</key>\n\t<string>17E262</string>\n</dict>\n</plist>\n' % (
udid)
uri = "https://fly.harmonygames.cn/udid/%s" % (random.choice(short))
# uri = "https://fly.harmonygames.cn/udid/%s" % ("bgql")
req = requests.post(uri, data=data)

Loading…
Cancel
Save