parent
8de6e4a87d
commit
789b9a0c58
@ -0,0 +1,18 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-15 19:22 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0026_auto_20200414_1505'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='apps', |
||||
name='issupersign', |
||||
field=models.BigIntegerField(default=False, verbose_name='是否超级签名包'), |
||||
), |
||||
] |
@ -0,0 +1,31 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-16 08:33 |
||||
|
||||
from django.db import migrations, models |
||||
import django.db.models.deletion |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0027_apps_issupersign'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.CreateModel( |
||||
name='AppUDID', |
||||
fields=[ |
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
('udid', models.CharField(db_index=True, max_length=64, unique=True, verbose_name='udid唯一标识')), |
||||
('product', models.CharField(db_index=True, max_length=64, verbose_name='产品')), |
||||
('serial', models.CharField(db_index=True, max_length=64, verbose_name='序列号')), |
||||
('version', models.CharField(db_index=True, max_length=64, verbose_name='型号')), |
||||
('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')), |
||||
], |
||||
options={ |
||||
'verbose_name': '应用详情', |
||||
'verbose_name_plural': '应用详情', |
||||
'unique_together': {('app_id', 'udid')}, |
||||
}, |
||||
), |
||||
] |
@ -0,0 +1,38 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-16 09:15 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0028_appudid'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='appudid', |
||||
name='iccid', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='型号'), |
||||
), |
||||
migrations.AddField( |
||||
model_name='appudid', |
||||
name='imei', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='型号'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='appudid', |
||||
name='product', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='产品'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='appudid', |
||||
name='serial', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='序列号'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='appudid', |
||||
name='version', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='型号'), |
||||
), |
||||
] |
@ -0,0 +1,18 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-16 10:31 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0029_auto_20200416_0915'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='appudid', |
||||
name='updated_time', |
||||
field=models.DateTimeField(auto_now=True, verbose_name='更新时间'), |
||||
), |
||||
] |
@ -0,0 +1,18 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-23 17:29 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0030_appudid_updated_time'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='appudid', |
||||
name='is_signed', |
||||
field=models.BooleanField(default=False, verbose_name='是否完成签名打包'), |
||||
), |
||||
] |
@ -0,0 +1,49 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-25 15:30 |
||||
|
||||
from django.conf import settings |
||||
from django.db import migrations, models |
||||
import django.db.models.deletion |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0031_appudid_is_signed'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.CreateModel( |
||||
name='APPSuperSignUsedInfo', |
||||
fields=[ |
||||
('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')), |
||||
('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': '设备使用统计', |
||||
'verbose_name_plural': '设备使用统计', |
||||
}, |
||||
), |
||||
migrations.CreateModel( |
||||
name='AppIOSDeveloperInfo', |
||||
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')), |
||||
('password', models.CharField(max_length=64)), |
||||
('is_actived', models.BooleanField(default=False, verbose_name='是否已经激活')), |
||||
('usable_number', models.IntegerField(default=100, verbose_name='可使用设备数')), |
||||
('use_number', models.IntegerField(default=0, verbose_name='已消耗设备数')), |
||||
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), |
||||
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), |
||||
('user_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='用户ID')), |
||||
], |
||||
options={ |
||||
'verbose_name': '苹果开发者账户', |
||||
'verbose_name_plural': '苹果开发者账户', |
||||
}, |
||||
), |
||||
] |
@ -0,0 +1,23 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-25 16:01 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0032_appiosdeveloperinfo_appsupersignusedinfo'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='appudid', |
||||
name='binary_file', |
||||
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='签名包名称'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='appiosdeveloperinfo', |
||||
name='name', |
||||
field=models.CharField(max_length=64, unique=True, verbose_name='开发者标识'), |
||||
), |
||||
] |
@ -0,0 +1,18 @@ |
||||
# Generated by Django 3.0.3 on 2020-04-25 16:12 |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('api', '0033_auto_20200425_1601'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='appiosdeveloperinfo', |
||||
name='certid', |
||||
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='超级签名自动创建证书ID'), |
||||
), |
||||
] |
@ -0,0 +1,96 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding:utf-8 -*- |
||||
# project: 4月 |
||||
# author: liuyu |
||||
# date: 2020/4/24 |
||||
|
||||
from api.utils.app.shellcmds import shell_command,use_user_pass |
||||
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): |
||||
if remote: |
||||
hostip="10.66.6.66" |
||||
port=65534 |
||||
user="root" |
||||
passwd="root" |
||||
result = use_user_pass(hostip,port,user,passwd,cmd) |
||||
print(result) |
||||
return result |
||||
else: |
||||
result = shell_command(cmd) |
||||
print(result) |
||||
return result |
||||
|
||||
|
||||
|
||||
class AppDeveloperApi(object): |
||||
def __init__(self,username,password,certid): |
||||
self.username = username |
||||
self.password = password |
||||
self.certid = certid |
||||
script_path=os.path.join(SUPER_SIGN_ROOT,'scripts','apple_api.rb') |
||||
self.cmd = "ruby %s '%s' '%s'" %(script_path,self.username,self.password) |
||||
|
||||
def create_cert(self,user_obj): |
||||
cert_dir_name = make_app_uuid(user_obj,self.username) |
||||
cert_dir_path = os.path.join(SUPER_SIGN_ROOT,cert_dir_name) |
||||
if not os.path.isdir(cert_dir_path): |
||||
os.makedirs(cert_dir_path) |
||||
file_format_path_name = os.path.join(cert_dir_path,cert_dir_name) |
||||
self.cmd=self.cmd + " cert add '%s'" %(file_format_path_name) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
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) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
def del_profile(self,bundleId,app_id): |
||||
self.cmd=self.cmd + " profile del %s %s" %(bundleId,app_id) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
def set_device_status(self,status,device_udid): |
||||
if status == "enable": |
||||
self.cmd=self.cmd + " device enable %s" %(device_udid) |
||||
else: |
||||
self.cmd=self.cmd + " device disable %s" %(device_udid) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
def add_device(self,device_udid,device_name): |
||||
self.cmd=self.cmd + " device add %s %s" %(device_udid,device_name) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
def add_app(self,bundleId,app_id): |
||||
self.cmd=self.cmd + " app add %s %s" %(bundleId,app_id) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
def del_app(self,bundleId): |
||||
self.cmd=self.cmd + " app del %s " %(bundleId) |
||||
result = exec_shell(self.cmd) |
||||
print(result) |
||||
|
||||
# appdev = AppDeveloperApi("hehehuyu521@163.com","Hehehuyu123") |
||||
# appdev.create_cert() |
||||
# appdev.get_profile('com.hehegames.NenJiangMaJiang',"e6f0c1aeee6853af9c21651654a812e7","6dd86c12ab5506a1f7e45b0f58b6b1448f5cdf54","iPad5,1") |
||||
# # e6f0c1aeee6853af9c21651654a812e7_dis.mobileprovision |
||||
|
||||
class ResignApp(object): |
||||
|
||||
def __init__(self,my_local_key,app_dev_pem): |
||||
self.my_local_key=my_local_key |
||||
self.app_dev_pem = app_dev_pem |
||||
# script_path=os.path.join(SUPER_SIGN_ROOT,'scripts','apple_api.rb') |
||||
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) |
||||
print(result) |
@ -0,0 +1,127 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding:utf-8 -*- |
||||
# project: 3月 |
||||
# author: liuyu |
||||
# date: 2020/3/6 |
||||
|
||||
import time,re,os |
||||
from subprocess import Popen, PIPE |
||||
import logging |
||||
import paramiko,json |
||||
import socket |
||||
|
||||
def default_result(): |
||||
return {'exit_code': '99', 'return_info': 'Failed to run, function_name is not existed'} |
||||
|
||||
|
||||
def portisonline(host,port): |
||||
result={} |
||||
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
sk.settimeout(3) |
||||
result["host"] = host |
||||
result["port"]=port |
||||
result["functionname"]="CHECK_HOST_ONLINE:" |
||||
try: |
||||
sk.connect((host,port)) |
||||
result["message"]="Connection success" |
||||
result["code"]=0 |
||||
except Exception: |
||||
result["message"]="SSH Port Connection refused" |
||||
result["code"]=1 |
||||
sk.close() |
||||
return result |
||||
|
||||
|
||||
|
||||
|
||||
class SSHConnection(object): |
||||
def __init__(self, host, port, username, password): |
||||
self._host = host |
||||
self._port = port |
||||
self._username = username |
||||
self._password = password |
||||
self._transport = None |
||||
self._sftp = None |
||||
self._client = None |
||||
self._connect() |
||||
|
||||
def _connect(self): |
||||
transport = paramiko.Transport((self._host, self._port)) |
||||
transport.connect(username=self._username, password=self._password) |
||||
self._transport = transport |
||||
|
||||
#下载 |
||||
def download(self, remotepath, localpath): |
||||
if self._sftp is None: |
||||
self._sftp = paramiko.SFTPClient.from_transport(self._transport) |
||||
self._sftp.get(remotepath, localpath) |
||||
self.close() |
||||
|
||||
#上传 |
||||
def put(self, localpath, remotepath): |
||||
if self._sftp is None: |
||||
self._sftp = paramiko.SFTPClient.from_transport(self._transport) |
||||
self.exec_command('mkdir -p %s'%(os.path.dirname(remotepath))) |
||||
self._sftp.put(localpath, remotepath) |
||||
self.close() |
||||
|
||||
|
||||
#执行命令 |
||||
def exec_command(self, command): |
||||
if self._client is None: |
||||
self._client = paramiko.SSHClient() |
||||
self._client._transport = self._transport |
||||
stdin, stdout, stderr = self._client.exec_command(command) |
||||
data = stdout.read() |
||||
if len(data) > 0: |
||||
return {'status':0,'infos':data} |
||||
err = stderr.read() |
||||
if len(err) > 0: |
||||
return {'status':1,'infos':err} |
||||
return {'status': 0, 'infos': data} |
||||
|
||||
def close(self): |
||||
if self._transport: |
||||
self._transport.close() |
||||
if self._client: |
||||
self._client.close() |
||||
|
||||
def shell_command(cmdstrs): |
||||
cmdresult = re.split(r'\s+', cmdstrs) |
||||
result = default_result() |
||||
result['return_info'] = '' |
||||
shell_start_time = time.time() |
||||
child = Popen(cmdresult, shell=True, stdout=PIPE, stderr=PIPE) |
||||
out, err = child.communicate() |
||||
shell_end_time = time.time() |
||||
result['shell_run_time'] = shell_end_time - shell_start_time |
||||
out = out.strip(b'\n') |
||||
result['return_info'] = out |
||||
result['exit_code'] = child.returncode |
||||
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) |
||||
if checkinfo["code"] != 0: |
||||
result['shell_run_time'] = 0 |
||||
result['return_info'] = json.dumps(checkinfo) |
||||
result['exit_code'] = checkinfo["code"] |
||||
else: |
||||
conn = SSHConnection(hostip, port, user, passwd) |
||||
result['return_info'] = '' |
||||
shell_start_time = time.time() |
||||
out=conn.exec_command(cmdstrs) |
||||
shell_end_time = time.time() |
||||
result['shell_run_time'] = shell_end_time - shell_start_time |
||||
outs =str(out['infos'],'utf-8') |
||||
outs = outs.strip('\n') |
||||
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'])) |
||||
conn.close() |
||||
return result |
||||
|
||||
|
@ -0,0 +1,163 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding:utf-8 -*- |
||||
# project: 3月 |
||||
# author: liuyu |
||||
# date: 2020/3/6 |
||||
|
||||
import uuid, xmltodict,os |
||||
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 |
||||
from api.utils.app.randomstrings import make_app_uuid,make_from_user_uuid |
||||
from django.db.models import F |
||||
|
||||
def udid_bytes_to_dict(xml_stream): |
||||
new_uuid_info = {} |
||||
try: |
||||
a = xml_stream.find('<plist') |
||||
b = xml_stream.find('</plist>') |
||||
xml_dict = xmltodict.parse(xml_stream[a:b + 8]) # 解析xml字符串 |
||||
for i in range(len(xml_dict['plist']['dict']['key'])): |
||||
new_uuid_info[xml_dict['plist']['dict']['key'][i].lower()] = xml_dict['plist']['dict']['string'][i] |
||||
except Exception as e: |
||||
print(e) |
||||
return new_uuid_info |
||||
|
||||
|
||||
def make_udid_mobileconfig(udid_url, PayloadOrganization, PayloadUUID=uuid.uuid1(), PayloadDescription='本文件仅用来获取设备ID', |
||||
PayloadDisplayName='查询设备UDID'): |
||||
# <!--参考:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html--> |
||||
mobileconfig = ''' |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>PayloadContent</key> |
||||
<dict> |
||||
<key>URL</key> |
||||
<string>%s</string> |
||||
<key>DeviceAttributes</key> |
||||
<array> |
||||
<string>SERIAL</string> |
||||
<string>UDID</string> |
||||
<string>IMEI</string> |
||||
<string>ICCID</string> |
||||
<string>VERSION</string> |
||||
<string>PRODUCT</string> |
||||
</array> |
||||
</dict> |
||||
<key>PayloadOrganization</key> |
||||
<string>%s</string> |
||||
<key>PayloadDisplayName</key> |
||||
<string>%s</string> |
||||
<key>PayloadVersion</key> |
||||
<integer>1</integer> |
||||
<key>PayloadUUID</key> |
||||
<string>%s</string> |
||||
<key>PayloadIdentifier</key> |
||||
<string>%s.profile-service</string> |
||||
<key>PayloadDescription</key> |
||||
<string>%s</string> |
||||
<key>PayloadType</key> |
||||
<string>Profile Service</string> |
||||
</dict> |
||||
</plist>''' % (udid_url, PayloadOrganization, PayloadDisplayName, PayloadUUID, PayloadOrganization, PayloadDescription) |
||||
return mobileconfig |
||||
|
||||
|
||||
def get_post_udid_url(request, short): |
||||
server_domain = get_http_server_doamin(request) |
||||
|
||||
PATH_INFO = request.META.get('PATH_INFO') |
||||
PATH_INFO_lists = PATH_INFO.strip('/').split('/') |
||||
PATH_INFO_lists[-1] = 'udid' |
||||
PATH_INFO_lists.pop(-2) |
||||
PATH_INFO_lists.append(short) |
||||
PATH_INFO_lists.insert(0, server_domain) |
||||
udid_url = "/".join(PATH_INFO_lists) |
||||
return udid_url |
||||
|
||||
|
||||
def get_http_server_doamin(request): |
||||
server_domain = SERVER_DOMAIN.get('POST_UDID_DOMAIN', None) |
||||
if not server_domain or not server_domain.startswith("http"): |
||||
HTTP_HOST = request.META.get('HTTP_HOST') |
||||
SERVER_PROTOCOL = request.META.get('SERVER_PROTOCOL') |
||||
protocol = 'https' |
||||
if SERVER_PROTOCOL == 'HTTP/1.1': |
||||
protocol = 'http' |
||||
server_domain = "%s://%s" % (protocol, HTTP_HOST) |
||||
return server_domain |
||||
|
||||
def get_redirect_server_domain(request): |
||||
server_domain = SERVER_DOMAIN.get('REDIRECT_UDID_DOMAIN', None) |
||||
if not server_domain or not server_domain.startswith("http"): |
||||
HTTP_HOST = request.META.get('HTTP_HOST') |
||||
SERVER_PROTOCOL = request.META.get('SERVER_PROTOCOL') |
||||
protocol = 'https' |
||||
if SERVER_PROTOCOL == 'HTTP/1.1': |
||||
protocol = 'http' |
||||
server_domain = "%s://%s" % (protocol, HTTP_HOST) |
||||
return server_domain |
||||
|
||||
|
||||
class IosUtils(object): |
||||
def __init__(self,udid_info,app_obj): |
||||
self.udid_info=udid_info |
||||
self.app_obj = app_obj |
||||
self.user_obj = app_obj.user_id |
||||
self.get_developer_auth() |
||||
|
||||
|
||||
def get_developer_auth(self): |
||||
developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj,is_actived=True,use_number__lte=F("usable_number")).first() |
||||
auth = { |
||||
"username":developer_obj.email, |
||||
"password": developer_obj.password, |
||||
"certid":developer_obj.certid |
||||
} |
||||
self.auth = auth |
||||
|
||||
|
||||
def download_profile(self): |
||||
app_api_obj = AppDeveloperApi(** self.auth) |
||||
bundleId = self.app_obj.bundle_id |
||||
app_id=self.app_obj.app_id |
||||
device_udid= self.udid_info.get('udid') |
||||
device_name=self.udid_info.get('product') |
||||
app_api_obj.get_profile(bundleId,app_id,device_udid,device_name,self.get_profile_full_path()) |
||||
|
||||
def get_profile_full_path(self): |
||||
cert_dir_name = make_app_uuid(self.user_obj,self.auth.get("username")) |
||||
cert_dir_path = os.path.join(SUPER_SIGN_ROOT,cert_dir_name) |
||||
file_format_path_name = os.path.join(cert_dir_path,cert_dir_name,"profile") |
||||
if not os.path.isdir(file_format_path_name): |
||||
os.makedirs(file_format_path_name) |
||||
provisionName = os.path.join(file_format_path_name,self.app_obj.app_id) |
||||
return provisionName+ '.mobileprovision' |
||||
|
||||
def resign(self): |
||||
self.download_profile() |
||||
cert_dir_name = make_app_uuid(self.app_obj.user_id,self.auth.get("username")) |
||||
cert_dir_path = os.path.join(SUPER_SIGN_ROOT,cert_dir_name) |
||||
if not os.path.isdir(cert_dir_path): |
||||
os.makedirs(cert_dir_path) |
||||
file_format_path_name = os.path.join(cert_dir_path,cert_dir_name) |
||||
|
||||
my_local_key=file_format_path_name+".key" |
||||
app_dev_pem =file_format_path_name+".pem" |
||||
ResignAppObj = ResignApp(my_local_key,app_dev_pem) |
||||
|
||||
random_file_name = make_from_user_uuid(self.user_obj) |
||||
|
||||
release_obj = AppReleaseInfo.objects.filter(app_id=self.app_obj,is_master=True).first() |
||||
|
||||
org_file = os.path.join(MEDIA_ROOT, release_obj.release_id + ".ipa") |
||||
new_file = os.path.join(MEDIA_ROOT, random_file_name + ".ipa") |
||||
ResignAppObj.sign(self.get_profile_full_path(),org_file,new_file) |
||||
|
||||
newdata={ |
||||
"is_signed":True, |
||||
"binary_file":random_file_name + ".ipa" |
||||
} |
||||
AppUDID.objects.filter(app_id=self.app_obj,udid=self.udid_info.get('udid')).update(**newdata) |
@ -1,3 +0,0 @@ |
||||
from django.shortcuts import render |
||||
|
||||
# Create your views here. |
@ -0,0 +1,157 @@ |
||||
#!/usr/bin/ruby |
||||
# -*- coding: UTF-8 -*- |
||||
|
||||
require "spaceship" |
||||
|
||||
class DevelopPortalHandle |
||||
def login(username,password) |
||||
Spaceship::Portal.login(username,password) |
||||
end |
||||
|
||||
def createCert(file_format_path_name) |
||||
csr, pkey = Spaceship::Portal.certificate.create_certificate_signing_request |
||||
cert=Spaceship::Portal.certificate.production.create!(csr: csr) |
||||
File.write(file_format_path_name+".key",pkey) |
||||
File.write(file_format_path_name+".cer",cert.download_raw) |
||||
File.write(file_format_path_name+".pem",cert.download) |
||||
File.write(file_format_path_name+".info",cert) |
||||
end |
||||
|
||||
def createApp(appid,appname) |
||||
app = Spaceship::Portal.app.find(appid) |
||||
if !app then |
||||
app = Spaceship::Portal.app.create!(bundle_id: appid, name: appname) |
||||
app.update_service(Spaceship::Portal.app_service.push_notification.on) |
||||
app.update_service(Spaceship::Portal.app_service.vpn_configuration.on) |
||||
end |
||||
end |
||||
|
||||
def deleteApp(appid) |
||||
app = Spaceship::Portal.app.find(appid) |
||||
if app then |
||||
app.delete! |
||||
end |
||||
end |
||||
|
||||
#appstore or inHouse |
||||
def createDistributionProvision(provisioningClass,appid,provisionName,certid) |
||||
cert = Spaceship::Portal.certificate.Production.find(id=certid) |
||||
if !cert then |
||||
cert = Spaceship::Portal.certificate.production.all.last |
||||
end |
||||
profile = provisioningClass.create!(bundle_id: appid,certificate:cert,name:provisionName + '_dis') |
||||
return profile |
||||
end |
||||
|
||||
#appstore or inHouse |
||||
def downloadDistributionProvision(provisioningClass,appid,provisionName,certid) |
||||
#查找有没有provision文件 |
||||
filtered_profiles = provisioningClass.find_by_bundle_id(bundle_id: appid) |
||||
profile = nil |
||||
if 0 < filtered_profiles.length then |
||||
profile = filtered_profiles[0] |
||||
elsif 0 == filtered_profiles.length then |
||||
profile = createDistributionProvision(provisioningClass,appid,provisionName,certid) |
||||
end |
||||
|
||||
#没有找到就创建,找到就下载 |
||||
File.write(provisionName, profile.download) |
||||
return provisionFileName |
||||
end |
||||
|
||||
def delete_profile(provisioningClass,appid) |
||||
filtered_profiles = provisioningClass.find_by_bundle_id(bundle_id: appid) |
||||
profile = nil |
||||
if 0 < filtered_profiles.length then |
||||
profile = filtered_profiles[0] |
||||
profile.delete! |
||||
end |
||||
end |
||||
def addDevice(device_name,device_udid) |
||||
device = Spaceship::Portal.device.find_by_udid(device_udid, include_disabled: false) |
||||
if !device then |
||||
Spaceship::Portal.device.create!(name: device_name, udid: device_udid) |
||||
end |
||||
end |
||||
|
||||
def enableDevice(device_udid) |
||||
device=Spaceship::Portal.device.find_by_udid(device_udid, include_disabled: true) |
||||
if device then |
||||
device.enable! |
||||
end |
||||
end |
||||
|
||||
def disableDevice(device_udid) |
||||
device = Spaceship::Portal.device.find_by_udid(device_udid) |
||||
if device then |
||||
device.disable! |
||||
end |
||||
end |
||||
|
||||
end |
||||
|
||||
handle = DevelopPortalHandle.new() |
||||
handle.login(ARGV[0],ARGV[1]) |
||||
function = ARGV[2] |
||||
|
||||
case function |
||||
when "device" |
||||
action = ARGV[3] |
||||
device_udid = ARGV[4] |
||||
device_name = ARGV[5] |
||||
|
||||
case action |
||||
when "add" |
||||
device_name = device_udid+','+device_udid |
||||
handle.addDevice(device_name,device_udid) |
||||
when "enable" |
||||
handle.enableDevice(device_udid) |
||||
when "disable" |
||||
handle.disableDevice(device_udid) |
||||
end |
||||
|
||||
when "app" |
||||
action = ARGV[3] |
||||
app_id = ARGV[4] |
||||
app_name = ARGV[5] |
||||
appid = app_id+app_name |
||||
|
||||
case action |
||||
when "add" |
||||
handle.createApp(appid,app_name) |
||||
when "del" |
||||
handle.deleteApp(appid) |
||||
handle.delete_profile(Spaceship::Portal.provisioning_profile.ad_hoc,appid) |
||||
end |
||||
when "profile" |
||||
action = ARGV[3] |
||||
app_id = ARGV[4] |
||||
app_name = ARGV[5] |
||||
appid = app_id+app_name |
||||
|
||||
case action |
||||
when "add" |
||||
device_udid = ARGV[6] |
||||
device_name = ARGV[7] |
||||
certid = ARGV[8] |
||||
provisionName = ARGV[9] |
||||
handle.createApp(appid,app_name) |
||||
handle.addDevice(device_name,device_udid) |
||||
provisionPath = handle.downloadDistributionProvision(Spaceship::Portal.provisioning_profile.ad_hoc,appid,provisionName,certid) |
||||
when "del" |
||||
handle.delete_profile(Spaceship::Portal.provisioning_profile.ad_hoc,appid) |
||||
end |
||||
|
||||
when "cert" |
||||
action = ARGV[3] |
||||
file_format_path_name = ARGV[4] |
||||
case action |
||||
when "add" |
||||
handle.createCert(file_format_path_name) |
||||
end |
||||
|
||||
else |
||||
puts "error" |
||||
end |
||||
|
||||
|
Loading…
Reference in new issue