diff --git a/fir_client/src/components/FirAppInfossecurity.vue b/fir_client/src/components/FirAppInfossecurity.vue
index c78d1bf..0984e3f 100644
--- a/fir_client/src/components/FirAppInfossecurity.vue
+++ b/fir_client/src/components/FirAppInfossecurity.vue
@@ -54,7 +54,7 @@
inactive-value="off">
-
+ 清理开发者账户脏数据
@@ -79,9 +79,13 @@
passwordflag:false,
showdownloadflag:false,
showsupersignflag:false,
+ clecount:0
}
},
methods: {
+ clean_app(){
+ this.saveappinfo({"clean":true})
+ },
saveappinfo(data) {
updateapp(data => {
if (data.code === 1000) {
diff --git a/fir_client/src/components/FirApps.vue b/fir_client/src/components/FirApps.vue
index 29159b9..d3a89aa 100644
--- a/fir_client/src/components/FirApps.vue
+++ b/fir_client/src/components/FirApps.vue
@@ -8,11 +8,15 @@
:title="getDelappTitle"
:visible.sync="willDeleteApp"
width="50%">
- 删除后不可恢复,请谨慎操作
+
+ 请先在权限管理页面关闭超级签名
+ 删除后不可恢复,请谨慎操作
+
+ 确 定
+ 确 定
+
@@ -337,18 +341,21 @@
打包类型: |
-
- {{ r.master_release.release_type|getiOStype }}
- |
+
+
+ {{ r.master_release.release_type|getiOStype }}
+ 超级签名
+
+ |
第三方平台下载: |
-
-
- {{ r.master_release.binary_url| autoformat}}
-
-
+
+
+ {{ r.master_release.binary_url| autoformat}}
+
+
|
@@ -364,8 +371,10 @@
预览
+
-
@@ -739,7 +748,8 @@
return size / 1000;
},
autoformat: function (packname) {
- if ((packname.length) > 20) {
+
+ if (packname && (packname.length) > 20) {
return packname.split('').slice(0, 20).join('') + '...';
} else {
return packname
diff --git a/fir_client/src/components/FirDownload.vue b/fir_client/src/components/FirDownload.vue
index 1444c04..6e4b77c 100644
--- a/fir_client/src/components/FirDownload.vue
+++ b/fir_client/src/components/FirDownload.vue
@@ -31,7 +31,8 @@
- {{ mcurrentappinfo.release_type|getiOStype }}
+ 超级签
+ {{ mcurrentappinfo.release_type|getiOStype }}
@@ -175,7 +176,10 @@
this.isdownload = true;
getdownloadurl(res=>{
if(res.code === 1000){
-
+ if(res.data.download_url === ""){
+ window.location.href=this.full_url;
+ return
+ }
if(this.currentappinfo.type === 1){
if(this.currentappinfo.issupersign && this.udid !== this.$route.query.udid){
if(this.agent !== ''){
@@ -209,7 +213,7 @@
'short': this.currentappinfo.short,
'release_id': this.mcurrentappinfo.release_id,
'password':this.password,
- 'udid':this.udid
+ 'udid':this.udid,
},
'app_id': this.currentappinfo.app_id
})
@@ -223,7 +227,7 @@
})
},
getDownloadTokenFun() {
- let params={ "short": this.$route.params.short };
+ let params={ "short": this.$route.params.short ,"time":new Date().getTime()};
if(this.$route.query.release_id){
params["release_id"]=this.$route.query.release_id
}
@@ -363,7 +367,7 @@
this.getAgent();
}, mounted() {
this.getDownloadTokenFun();
- this.full_url = location.href;
+ this.full_url = location.href.split("?")[0];
this.qrcode();
},filters:{
getiOStype: function (type) {
diff --git a/fir_client/src/components/FirSuperSignBase.vue b/fir_client/src/components/FirSuperSignBase.vue
index b95a57b..b15638a 100644
--- a/fir_client/src/components/FirSuperSignBase.vue
+++ b/fir_client/src/components/FirSuperSignBase.vue
@@ -1,5 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存
+ 取消
+
+
+
+
+
+
+
+
+
+
+
+
+
+ width="110">
已激活
- 未激活
+ 点击激活
@@ -55,7 +98,7 @@
编辑
+ @click="handleEditDeveloper(scope.row)">编辑
- 添加开发者
+ 添加开发者
{
+ if(value.toString().length>5 && this.IsNum(value)){
+ this.iosdeveloperFun({"methods":"PUT","data":{"email":developer.email,"act":"nowactive","code":value}});
+ }
+ }).catch(() => {
+ this.$message({
+ type: 'info',
+ message: '取消激活'
+ });
+ });
+ },
+ activedeveloperFun(developer){
+ this.iosdeveloperFun({"methods":"PUT","data":{"email":developer.email,"act":"preactive"}});
+ this.inputcode(developer)
+ },
+ canceledit(){
+ this.dialogaddDeveloperVisible=false;
+ this.editdeveloperinfo={};
+ this.isedit=false;
+ this.placeholder=""
+ },
+ handleEditDeveloper(developer_info){
+ this.editdeveloperinfo=developer_info;
+ this.title='编辑开发者账户';
+ this.dialogaddDeveloperVisible=true;
+ this.isedit=true;
+ this.placeholder="为空表示不修改密码"
+ },
+ updateorcreate(){
+ if(this.isedit){
+ this.iosdeveloperFun({"methods":"PUT","data":this.editdeveloperinfo})
+ }else {
+ if(this.editdeveloperinfo.email && this.editdeveloperinfo.password && this.editdeveloperinfo.usable_number ){
+ this.iosdeveloperFun({"methods":"POST","data":this.editdeveloperinfo});
+ }else {
+ this.$message.warning("输入格式有误")
+ }
+ }
+ },
handleDelete(b){
// eslint-disable-next-line no-console
console.log(b)
@@ -218,6 +321,9 @@
this.iosdevicesFun()
}else if(tab.name === "devicesudid"){
this.iosdevicesudidFun('GET')
+ }else if(tab.name === "adddeveloper"){
+ this.title='新增私有开发者账户';
+ this.dialogaddDeveloperVisible=true;
}
},
@@ -250,18 +356,27 @@
"methods":"GET"
})
},
- iosdeveloperFun(){
+ iosdeveloperFun(params){
iosdeveloper(data=>{
if(data.code === 1000){
this.app_developer_lists = data.data;
this.$store.dispatch("getUser",data.userinfo);
this.$store.dispatch('doucurrentapp', {});
- // eslint-disable-next-line no-console
- console.log(data)
+ if(this.dialogaddDeveloperVisible){
+ this.canceledit();
+ this.$message.success("操作成功");
+ this.activeName="iosdeveloper";
+ this.editdeveloperinfo={};
+
+ }
}
- },{
- "methods":"GET"
- })
+ else if(data.code === 1008){
+ this.$message.error(data.msg);
+ }
+ else {
+ this.$message.error("操作失败")
+ }
+ },params)
},
iosdevicesudidFun(action,data){
iosdevicesudid(data=>{
@@ -274,7 +389,7 @@
}
}, mounted() {
- this.iosdeveloperFun()
+ this.iosdeveloperFun({"methods":"GET"})
}, watch: {
// eslint-disable-next-line no-unused-vars
udidsearch: function (val, oldVal) {
diff --git a/fir_ser/api/admin.py b/fir_ser/api/admin.py
index bfe4cad..5b3302e 100644
--- a/fir_ser/api/admin.py
+++ b/fir_ser/api/admin.py
@@ -13,4 +13,5 @@ admin.site.register(AppStorage)
admin.site.register(AppUDID)
admin.site.register(AppIOSDeveloperInfo)
admin.site.register(APPSuperSignUsedInfo)
+admin.site.register(APPToDeveloper)
diff --git a/fir_ser/api/migrations/0001_initial.py b/fir_ser/api/migrations/0001_initial.py
index 00df62d..4974a68 100644
--- a/fir_ser/api/migrations/0001_initial.py
+++ b/fir_ser/api/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 3.0.3 on 2020-03-03 11:27
+# Generated by Django 3.0.3 on 2020-05-01 16:40
from django.conf import settings
import django.contrib.auth.models
@@ -19,6 +19,7 @@ class Migration(migrations.Migration):
name='UserInfo',
fields=[
('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')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
@@ -26,21 +27,22 @@ class Migration(migrations.Migration):
('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')),
- ('uid', models.CharField(max_length=64, unique=True)),
+ ('uid', models.CharField(db_index=True, max_length=64, unique=True)),
('mobile', models.BigIntegerField(help_text='用于手机验证码登录', null=True, unique=True, verbose_name='手机')),
- ('qq', models.CharField(blank=True, db_index=True, max_length=64, null=True, verbose_name='QQ')),
- ('is_active', models.BooleanField(default=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='性别')),
- ('password', models.CharField(help_text="重置密码", max_length=128, verbose_name='password')),
- ('head_img', models.CharField(default='/static/frontend/head_portrait/logo@2x.png', max_length=256, 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='角色')),
('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')),
- ('user_permissions', 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')),
],
options={
'verbose_name': '账户信息',
@@ -50,6 +52,51 @@ class Migration(migrations.Migration):
('objects', django.contrib.auth.models.UserManager()),
],
),
+ 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='是否已经激活')),
+ ('certid', models.CharField(blank=True, max_length=64, null=True, verbose_name='超级签名自动创建证书ID')),
+ ('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='更新时间')),
+ ('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')),
+ ],
+ options={
+ 'verbose_name': '苹果开发者账户',
+ 'verbose_name_plural': '苹果开发者账户',
+ },
+ ),
+ migrations.CreateModel(
+ name='Apps',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('app_id', models.CharField(db_index=True, max_length=64, unique=True)),
+ ('type', models.SmallIntegerField(choices=[(0, 'android'), (1, 'ios')], default=0, verbose_name='类型')),
+ ('name', models.CharField(blank=True, max_length=32, null=True, verbose_name='应用名称')),
+ ('short', models.CharField(db_index=True, max_length=16, unique=True, verbose_name='短链接')),
+ ('bundle_id', models.CharField(blank=True, max_length=64, verbose_name='bundle id')),
+ ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+ ('count_hits', models.BigIntegerField(default=0, verbose_name='下载次数')),
+ ('password', models.CharField(default='', help_text='默认 没有密码', max_length=32, verbose_name='访问密码')),
+ ('isshow', models.BigIntegerField(default=1, verbose_name='下载页可见')),
+ ('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')),
+ ],
+ options={
+ 'verbose_name': '应用信息',
+ 'verbose_name_plural': '应用信息',
+ },
+ ),
migrations.CreateModel(
name='VerifyName',
fields=[
@@ -70,50 +117,110 @@ class Migration(migrations.Migration):
name='Token',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('access_token', models.CharField(max_length=42, unique=True)),
+ ('access_token', models.CharField(max_length=64, unique=True)),
('created', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
- ('user', models.OneToOneField(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(
- name='Apps',
+ 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, verbose_name='udid唯一标识')),
+ ('product', models.CharField(blank=True, max_length=64, null=True, verbose_name='产品')),
+ ('serial', models.CharField(blank=True, max_length=64, null=True, verbose_name='序列号')),
+ ('version', models.CharField(blank=True, max_length=64, null=True, verbose_name='型号')),
+ ('imei', models.CharField(blank=True, max_length=64, null=True, verbose_name='型号')),
+ ('iccid', models.CharField(blank=True, max_length=64, null=True, verbose_name='型号')),
+ ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+ ('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')),
+ ],
+ options={
+ 'verbose_name': '设备详情',
+ 'verbose_name_plural': '设备详情',
+ 'unique_together': {('app_id', 'udid')},
+ },
+ ),
+ migrations.CreateModel(
+ name='APPSuperSignUsedInfo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('app_id', models.CharField(max_length=64, unique=True)),
- ('type', models.SmallIntegerField(choices=[(0, 'ios'), (1, 'android')], default=0, verbose_name='类型')),
- ('name', models.CharField(blank=True, max_length=32, null=True, verbose_name='应用名称')),
- ('short', models.CharField(max_length=16, unique=True, verbose_name='短链接')),
- ('bundle_id', models.CharField(blank=True, max_length=64, verbose_name='bundle id')),
- ('icon_url', models.CharField(blank=True, max_length=128, verbose_name='图标url')),
('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
- ('count_hits', models.BigIntegerField(verbose_name='下载次数')),
('updated_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
- ('has_combo', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='combo_app_info', to='api.Apps', 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')),
],
options={
- 'verbose_name': '应用信息',
- 'verbose_name_plural': '应用信息',
+ 'verbose_name': '设备使用统计',
+ 'verbose_name_plural': '设备使用统计',
+ },
+ ),
+ migrations.CreateModel(
+ name='AppStorage',
+ 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='存储类型')),
+ ('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='下载域名')),
+ ('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='额外参数')),
+ ('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')),
+ ],
+ options={
+ 'verbose_name': '存储配置',
+ 'verbose_name_plural': '存储配置',
},
),
migrations.CreateModel(
name='AppReleaseInfo',
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(max_length=64, unique=True, verbose_name='release 版本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')),
('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, '')], 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='APPurl')),
+ ('binary_url', models.CharField(blank=True, max_length=128, verbose_name='第三方下载URL')),
+ ('icon_url', models.CharField(blank=True, max_length=128, verbose_name='图标url')),
+ ('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': '应用详情',
'verbose_name_plural': '应用详情',
},
),
+ 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='存储'),
+ ),
+ 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'),
+ ),
+ migrations.AddIndex(
+ model_name='apps',
+ index=models.Index(fields=['app_id'], name='api_apps_app_id_4c0254_idx'),
+ ),
+ migrations.AddIndex(
+ model_name='apps',
+ index=models.Index(fields=['id', 'user_id', 'type'], name='api_apps_id_226a6b_idx'),
+ ),
]
diff --git a/fir_ser/api/migrations/0002_auto_20200303_1940.py b/fir_ser/api/migrations/0002_auto_20200303_1940.py
deleted file mode 100644
index e2dd26c..0000000
--- a/fir_ser/api/migrations/0002_auto_20200303_1940.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-03 11:40
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='apps',
- name='has_combo',
- field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='combo_app_info', to='api.Apps', verbose_name='关联应用'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0002_auto_20200503_1120.py b/fir_ser/api/migrations/0002_auto_20200503_1120.py
new file mode 100644
index 0000000..915b651
--- /dev/null
+++ b/fir_ser/api/migrations/0002_auto_20200503_1120.py
@@ -0,0 +1,26 @@
+# Generated by Django 3.0.3 on 2020-05-03 11:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='appiosdeveloperinfo',
+ name='email',
+ field=models.EmailField(blank=True, max_length=64, null=True, verbose_name='email address'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='appiosdeveloperinfo',
+ unique_together={('user_id', 'email')},
+ ),
+ migrations.RemoveField(
+ model_name='appiosdeveloperinfo',
+ name='name',
+ ),
+ ]
diff --git a/fir_ser/api/migrations/0003_apptodeveloper.py b/fir_ser/api/migrations/0003_apptodeveloper.py
new file mode 100644
index 0000000..946da00
--- /dev/null
+++ b/fir_ser/api/migrations/0003_apptodeveloper.py
@@ -0,0 +1,28 @@
+# Generated by Django 3.0.3 on 2020-05-03 21:16
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0002_auto_20200503_1120'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='APPToDeveloper',
+ fields=[
+ ('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='所使用苹果开发者账户')),
+ ],
+ options={
+ 'verbose_name': '设备使用统计',
+ 'verbose_name_plural': '设备使用统计',
+ },
+ ),
+ ]
diff --git a/fir_ser/api/migrations/0003_auto_20200306_1734.py b/fir_ser/api/migrations/0003_auto_20200306_1734.py
deleted file mode 100644
index 4e74e31..0000000
--- a/fir_ser/api/migrations/0003_auto_20200306_1734.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-06 09:34
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0002_auto_20200303_1940'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='app_id',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.Apps', verbose_name='属于哪个APP'),
- ),
- migrations.CreateModel(
- name='AppStorage',
- fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('app_file', models.FileField(upload_to='')),
- ('name', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='api.AppReleaseInfo')),
- ],
- ),
- ]
diff --git a/fir_ser/api/migrations/0004_auto_20200306_2331.py b/fir_ser/api/migrations/0004_auto_20200306_2331.py
deleted file mode 100644
index 4e3294f..0000000
--- a/fir_ser/api/migrations/0004_auto_20200306_2331.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-06 15:31
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0003_auto_20200306_1734'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='apps',
- name='icon_url',
- ),
- migrations.AddField(
- model_name='appreleaseinfo',
- name='icon_url',
- field=models.CharField(blank=True, max_length=128, verbose_name='图标url'),
- ),
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='release_type',
- field=models.SmallIntegerField(choices=[(0, 'android'), (1, 'adhoc'), (2, 'Inhouse'), (3, 'unknown')], default=0, verbose_name='版本类型'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0005_auto_20200307_0800.py b/fir_ser/api/migrations/0005_auto_20200307_0800.py
deleted file mode 100644
index 973a349..0000000
--- a/fir_ser/api/migrations/0005_auto_20200307_0800.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-07 00:00
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0004_auto_20200306_2331'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='apps',
- name='name',
- ),
- migrations.AddField(
- model_name='appreleaseinfo',
- name='name',
- field=models.CharField(blank=True, max_length=32, null=True, verbose_name='应用名称'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0006_auto_20200307_0810.py b/fir_ser/api/migrations/0006_auto_20200307_0810.py
deleted file mode 100644
index 18ae4d4..0000000
--- a/fir_ser/api/migrations/0006_auto_20200307_0810.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-07 00:10
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0005_auto_20200307_0800'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='appreleaseinfo',
- name='name',
- ),
- migrations.AddField(
- model_name='apps',
- name='name',
- field=models.CharField(blank=True, max_length=32, null=True, verbose_name='应用名称'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0007_appreleaseinfo_changelog.py b/fir_ser/api/migrations/0007_appreleaseinfo_changelog.py
deleted file mode 100644
index 65d7dda..0000000
--- a/fir_ser/api/migrations/0007_appreleaseinfo_changelog.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-07 01:59
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0006_auto_20200307_0810'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='appreleaseinfo',
- name='changelog',
- field=models.TextField(blank=True, default=None, null=True, verbose_name='更新日志'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0008_auto_20200307_1249.py b/fir_ser/api/migrations/0008_auto_20200307_1249.py
deleted file mode 100644
index 4b014d0..0000000
--- a/fir_ser/api/migrations/0008_auto_20200307_1249.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-07 04:49
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0007_appreleaseinfo_changelog'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='apps',
- name='description',
- field=models.TextField(blank=True, default=None, null=True, verbose_name='描述'),
- ),
- migrations.AlterField(
- model_name='apps',
- name='type',
- field=models.SmallIntegerField(choices=[(0, 'android'), (1, 'ios')], default=0, verbose_name='类型'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0009_auto_20200309_1424.py b/fir_ser/api/migrations/0009_auto_20200309_1424.py
deleted file mode 100644
index 33fe3a3..0000000
--- a/fir_ser/api/migrations/0009_auto_20200309_1424.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-09 06:24
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0008_auto_20200307_1249'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userinfo',
- name='domain_name',
- field=models.CharField(blank=True, max_length=64, null=True, verbose_name='域名'),
- ),
- migrations.AlterField(
- model_name='apps',
- name='count_hits',
- field=models.BigIntegerField(default=0, verbose_name='下载次数'),
- ),
- migrations.DeleteModel(
- name='AppStorage',
- ),
- ]
diff --git a/fir_ser/api/migrations/0010_auto_20200309_1918.py b/fir_ser/api/migrations/0010_auto_20200309_1918.py
deleted file mode 100644
index 8ec61a2..0000000
--- a/fir_ser/api/migrations/0010_auto_20200309_1918.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-09 11:18
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0009_auto_20200309_1424'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='userinfo',
- name='head_img',
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='password',
- field=models.CharField(max_length=128, verbose_name='password'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='qq',
- field=models.BigIntegerField(blank=True, db_index=True, max_length=64, null=True, verbose_name='QQ'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0011_auto_20200310_1019.py b/fir_ser/api/migrations/0011_auto_20200310_1019.py
deleted file mode 100644
index 30c0b58..0000000
--- a/fir_ser/api/migrations/0011_auto_20200310_1019.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-10 02:19
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0010_auto_20200309_1918'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userinfo',
- name='all_download_times',
- field=models.IntegerField(default=0, verbose_name='总共下载次数'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='qq',
- field=models.BigIntegerField(blank=True, db_index=True, null=True, verbose_name='QQ'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0012_userinfo_head_img.py b/fir_ser/api/migrations/0012_userinfo_head_img.py
deleted file mode 100644
index f116443..0000000
--- a/fir_ser/api/migrations/0012_userinfo_head_img.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-14 07:22
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0011_auto_20200310_1019'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userinfo',
- name='head_img',
- field=models.CharField(default='/static/frontend/head_portrait/logo@2x.png', max_length=256, verbose_name='个人头像'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0013_auto_20200323_2020.py b/fir_ser/api/migrations/0013_auto_20200323_2020.py
deleted file mode 100644
index aeaf200..0000000
--- a/fir_ser/api/migrations/0013_auto_20200323_2020.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-23 12:20
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0012_userinfo_head_img'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='is_master',
- field=models.BooleanField(default=True, verbose_name='是否master版本'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='head_img',
- field=models.CharField(default='/files/imgs/head_img.jpeg', max_length=256, verbose_name='个人头像'),
- ),
- migrations.CreateModel(
- name='AppStorage',
- 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='存储类型')),
- ('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')),
- ('additionalparameters', models.TextField(blank=True, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} 七牛云:{"domain_name":""}', max_length=256, null=True, verbose_name='额外参数')),
- ('created_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
- ('description', models.TextField(blank=True, default=None, null=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': '存储配置',
- },
- ),
- ]
diff --git a/fir_ser/api/migrations/0014_userinfo_storage.py b/fir_ser/api/migrations/0014_userinfo_storage.py
deleted file mode 100644
index 01a4d55..0000000
--- a/fir_ser/api/migrations/0014_userinfo_storage.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-23 12:35
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0013_auto_20200323_2020'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userinfo',
- name='storage',
- field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='app_storage', to='api.AppStorage', verbose_name='存储'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0015_auto_20200326_1454.py b/fir_ser/api/migrations/0015_auto_20200326_1454.py
deleted file mode 100644
index ee94f36..0000000
--- a/fir_ser/api/migrations/0015_auto_20200326_1454.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-26 06:54
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0014_userinfo_storage'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userinfo',
- name='history_release_limit',
- field=models.IntegerField(blank=True, default=10, null=True, verbose_name='app 历史记录版本'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='all_download_times',
- field=models.BigIntegerField(default=0, verbose_name='总共下载次数'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='head_img',
- field=models.CharField(default='head_img.jpeg', max_length=256, verbose_name='个人头像'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0016_auto_20200327_1121.py b/fir_ser/api/migrations/0016_auto_20200327_1121.py
deleted file mode 100644
index ccfcc63..0000000
--- a/fir_ser/api/migrations/0016_auto_20200327_1121.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-27 03:21
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0015_auto_20200326_1454'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appstorage',
- name='additionalparameters',
- field=models.TextField(blank=True, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} 七牛云:{"domain_name":""} 本地存储:{"domain_name":""}', max_length=256, null=True, verbose_name='额外参数'),
- ),
- migrations.AlterField(
- model_name='token',
- name='user',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='关联用户'),
- ),
- migrations.AlterField(
- model_name='userinfo',
- name='is_active',
- field=models.BooleanField(default=True, verbose_name='账户状态,默认启用'),
- ),
- migrations.AlterField(
- 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='存储'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0017_auto_20200331_1543.py b/fir_ser/api/migrations/0017_auto_20200331_1543.py
deleted file mode 100644
index 24ae0d7..0000000
--- a/fir_ser/api/migrations/0017_auto_20200331_1543.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.3 on 2020-03-31 07:43
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0016_auto_20200327_1121'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='appstorage',
- name='domain_name',
- field=models.CharField(blank=True, help_text='fly-storage.dvcloud.xin,可以自定义端口', max_length=128, null=True, verbose_name='下载域名'),
- ),
- migrations.AddField(
- model_name='appstorage',
- name='is_https',
- field=models.BooleanField(blank=True, default=True, null=True, verbose_name='是否支持https'),
- ),
- migrations.AlterField(
- model_name='appstorage',
- name='additionalparameters',
- field=models.TextField(blank=True, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} ', max_length=256, null=True, verbose_name='额外参数'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0018_auto_20200407_1134.py b/fir_ser/api/migrations/0018_auto_20200407_1134.py
deleted file mode 100644
index 3f8bf3c..0000000
--- a/fir_ser/api/migrations/0018_auto_20200407_1134.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-07 03:34
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0017_auto_20200331_1543'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='release_id',
- field=models.CharField(db_index=True, max_length=64, unique=True, verbose_name='release 版本id'),
- ),
- migrations.AlterField(
- model_name='apps',
- name='app_id',
- field=models.CharField(db_index=True, max_length=64, unique=True),
- ),
- migrations.AlterField(
- model_name='apps',
- name='short',
- field=models.CharField(db_index=True, max_length=16, unique=True, verbose_name='短链接'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0019_auto_20200407_1135.py b/fir_ser/api/migrations/0019_auto_20200407_1135.py
deleted file mode 100644
index eee5c64..0000000
--- a/fir_ser/api/migrations/0019_auto_20200407_1135.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-07 03:35
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0018_auto_20200407_1134'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='userinfo',
- name='uid',
- field=models.CharField(db_index=True, max_length=64, unique=True),
- ),
- ]
diff --git a/fir_ser/api/migrations/0020_auto_20200407_1157.py b/fir_ser/api/migrations/0020_auto_20200407_1157.py
deleted file mode 100644
index 05b1190..0000000
--- a/fir_ser/api/migrations/0020_auto_20200407_1157.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-07 03:57
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0019_auto_20200407_1135'),
- ]
-
- operations = [
- migrations.AddIndex(
- model_name='apps',
- index=models.Index(fields=['app_id'], name='api_apps_app_id_4c0254_idx'),
- ),
- migrations.AddIndex(
- model_name='apps',
- index=models.Index(fields=['id', 'user_id', 'type'], name='api_apps_id_226a6b_idx'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0021_auto_20200410_1141.py b/fir_ser/api/migrations/0021_auto_20200410_1141.py
deleted file mode 100644
index 4b4e4ba..0000000
--- a/fir_ser/api/migrations/0021_auto_20200410_1141.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-10 11:41
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0020_auto_20200407_1157'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='apps',
- name='password',
- field=models.CharField(default='', help_text='默认 没有密码', max_length=32, verbose_name='访问密码'),
- ),
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='binary_url',
- field=models.CharField(blank=True, max_length=128, verbose_name='第三方下载URL'),
- ),
- migrations.AlterField(
- model_name='token',
- name='access_token',
- field=models.CharField(max_length=64, unique=True),
- ),
- ]
diff --git a/fir_ser/api/migrations/0022_apps_isshow.py b/fir_ser/api/migrations/0022_apps_isshow.py
deleted file mode 100644
index b4b69a1..0000000
--- a/fir_ser/api/migrations/0022_apps_isshow.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-10 17:15
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0021_auto_20200410_1141'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='apps',
- name='isshow',
- field=models.BigIntegerField(default=1, verbose_name='下载页可见'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0023_appreleaseinfo_udid.py b/fir_ser/api/migrations/0023_appreleaseinfo_udid.py
deleted file mode 100644
index ea9ea3c..0000000
--- a/fir_ser/api/migrations/0023_appreleaseinfo_udid.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-11 10:20
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0022_apps_isshow'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='appreleaseinfo',
- name='udid',
- field=models.TextField(blank=True, default=None, null=True, verbose_name='ios内测版 udid'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0024_auto_20200413_1557.py b/fir_ser/api/migrations/0024_auto_20200413_1557.py
deleted file mode 100644
index 8ed2738..0000000
--- a/fir_ser/api/migrations/0024_auto_20200413_1557.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-13 15:57
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0023_appreleaseinfo_udid'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appreleaseinfo',
- name='udid',
- field=models.TextField(blank=True, default='', null=True, verbose_name='ios内测版 udid'),
- ),
- migrations.AlterField(
- model_name='appstorage',
- name='additionalparameters',
- field=models.TextField(blank=True, default=None, help_text='阿里云:{"sts_role_arn":"arn信息","endpoint":""} ', null=True, verbose_name='额外参数'),
- ),
- migrations.AlterField(
- model_name='appstorage',
- name='is_https',
- field=models.BooleanField(default=True, verbose_name='是否支持https'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0025_appstorage_updated_time.py b/fir_ser/api/migrations/0025_appstorage_updated_time.py
deleted file mode 100644
index 1b8e011..0000000
--- a/fir_ser/api/migrations/0025_appstorage_updated_time.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-14 10:26
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0024_auto_20200413_1557'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='appstorage',
- name='updated_time',
- field=models.DateTimeField(auto_now=True, verbose_name='更新时间'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0026_auto_20200414_1505.py b/fir_ser/api/migrations/0026_auto_20200414_1505.py
deleted file mode 100644
index 423312f..0000000
--- a/fir_ser/api/migrations/0026_auto_20200414_1505.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.0.3 on 2020-04-14 15:05
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0025_appstorage_updated_time'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='appstorage',
- name='description',
- field=models.TextField(blank=True, default='', null=True, verbose_name='备注'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0027_apps_issupersign.py b/fir_ser/api/migrations/0027_apps_issupersign.py
deleted file mode 100644
index cbef2cd..0000000
--- a/fir_ser/api/migrations/0027_apps_issupersign.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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='是否超级签名包'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0028_appudid.py b/fir_ser/api/migrations/0028_appudid.py
deleted file mode 100644
index e9f921c..0000000
--- a/fir_ser/api/migrations/0028_appudid.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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')},
- },
- ),
- ]
diff --git a/fir_ser/api/migrations/0029_auto_20200416_0915.py b/fir_ser/api/migrations/0029_auto_20200416_0915.py
deleted file mode 100644
index 4ba73f8..0000000
--- a/fir_ser/api/migrations/0029_auto_20200416_0915.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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='型号'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0030_appudid_updated_time.py b/fir_ser/api/migrations/0030_appudid_updated_time.py
deleted file mode 100644
index 5cb052b..0000000
--- a/fir_ser/api/migrations/0030_appudid_updated_time.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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='更新时间'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0031_appudid_is_signed.py b/fir_ser/api/migrations/0031_appudid_is_signed.py
deleted file mode 100644
index bcef040..0000000
--- a/fir_ser/api/migrations/0031_appudid_is_signed.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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='是否完成签名打包'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0032_appiosdeveloperinfo_appsupersignusedinfo.py b/fir_ser/api/migrations/0032_appiosdeveloperinfo_appsupersignusedinfo.py
deleted file mode 100644
index 4f82252..0000000
--- a/fir_ser/api/migrations/0032_appiosdeveloperinfo_appsupersignusedinfo.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# 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': '苹果开发者账户',
- },
- ),
- ]
diff --git a/fir_ser/api/migrations/0033_auto_20200425_1601.py b/fir_ser/api/migrations/0033_auto_20200425_1601.py
deleted file mode 100644
index 647c4df..0000000
--- a/fir_ser/api/migrations/0033_auto_20200425_1601.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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='开发者标识'),
- ),
- ]
diff --git a/fir_ser/api/migrations/0034_appiosdeveloperinfo_certid.py b/fir_ser/api/migrations/0034_appiosdeveloperinfo_certid.py
deleted file mode 100644
index 9714ece..0000000
--- a/fir_ser/api/migrations/0034_appiosdeveloperinfo_certid.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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'),
- ),
- ]
diff --git a/fir_ser/api/models.py b/fir_ser/api/models.py
index 613ca1a..b047a0f 100644
--- a/fir_ser/api/models.py
+++ b/fir_ser/api/models.py
@@ -190,11 +190,9 @@ class AppUDID(models.Model):
class AppIOSDeveloperInfo(models.Model):
user_id = models.ForeignKey(to="UserInfo",verbose_name="用户ID",on_delete=models.CASCADE)
- name = models.CharField(max_length=64,verbose_name="开发者标识",unique=True)
email = models.EmailField(
verbose_name='email address',
max_length=64,
- unique=True,
blank=True,
null=True
)
@@ -210,10 +208,12 @@ class AppIOSDeveloperInfo(models.Model):
class Meta:
verbose_name = '苹果开发者账户'
verbose_name_plural = "苹果开发者账户"
+ unique_together = ('user_id', 'email',)
+
def __str__(self):
- return "%s-%s" % (self.name,self.email)
+ return "%s-%s" % (self.user_id,self.email)
class APPSuperSignUsedInfo(models.Model):
user_id = models.ForeignKey(to="UserInfo",verbose_name="用户ID",on_delete=models.CASCADE)
@@ -227,4 +227,17 @@ class APPSuperSignUsedInfo(models.Model):
verbose_name_plural = "设备使用统计"
def __str__(self):
- return "%s-%s-%s" % (self.user_id,self.app_id,self.udid)
\ No newline at end of file
+ return "%s-%s-%s" % (self.user_id,self.app_id,self.udid)
+
+class APPToDeveloper(models.Model):
+ app_id = models.ForeignKey(to="Apps", on_delete=models.CASCADE, verbose_name="属于哪个APP")
+ developerid = models.ForeignKey(to="AppIOSDeveloperInfo",on_delete=models.CASCADE, verbose_name="所使用苹果开发者账户")
+ binary_file = models.CharField(max_length=128,blank=True,verbose_name="签名包名称",null=True)
+ updated_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
+
+ class Meta:
+ verbose_name = '应用开发者绑定'
+ verbose_name_plural = "应用开发者绑定"
+
+ def __str__(self):
+ return "%s-%s-%s" % (self.developerid,self.app_id,self.binary_file)
\ No newline at end of file
diff --git a/fir_ser/api/utils/app/iossignapi.py b/fir_ser/api/utils/app/iossignapi.py
index d103d91..e47ed07 100644
--- a/fir_ser/api/utils/app/iossignapi.py
+++ b/fir_ser/api/utils/app/iossignapi.py
@@ -9,7 +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):
+def exec_shell(cmd,remote=False,timeout=None):
if remote:
hostip="10.66.6.66"
port=65534
@@ -20,10 +20,10 @@ def exec_shell(cmd,remote=False):
return result
else:
print(cmd)
- result = shell_command(cmd)
+ result = shell_command(cmd,timeout)
print(result)
if result.get("exit_code") != 0 :
- raise
+ return False
return result
@@ -36,6 +36,20 @@ class AppDeveloperApi(object):
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 active(self,code):
+ timeout=10
+ self.cmd = self.cmd + " active "
+ if code:
+ self.cmd = "echo %s | %s" %(code,self.cmd)
+ timeout=None
+ try:
+ result = exec_shell(self.cmd,timeout=timeout)
+ if result["exit_code"] == 0:
+ return True
+ except Exception as e:
+ print(e)
+ return False
+
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)
@@ -68,8 +82,8 @@ class AppDeveloperApi(object):
self.cmd=self.cmd + " app add '%s' '%s'" %(bundleId,app_id)
result = exec_shell(self.cmd)
- def del_app(self,bundleId):
- self.cmd=self.cmd + " app del '%s' " %(bundleId)
+ def del_app(self,bundleId,app_id):
+ self.cmd=self.cmd + " app del '%s' '%s'" %(bundleId,app_id)
result = exec_shell(self.cmd)
# appdev = AppDeveloperApi("hehehuyu521@163.com","Hehehuyu123")
diff --git a/fir_ser/api/utils/app/shellcmds.py b/fir_ser/api/utils/app/shellcmds.py
index 1f8c8d2..0b40b78 100644
--- a/fir_ser/api/utils/app/shellcmds.py
+++ b/fir_ser/api/utils/app/shellcmds.py
@@ -3,8 +3,7 @@
# project: 3月
# author: liuyu
# date: 2020/3/6
-
-import time,re,os
+import time,re,os,signal
from subprocess import Popen, PIPE
import logging
import paramiko,json
@@ -86,13 +85,23 @@ class SSHConnection(object):
if self._client:
self._client.close()
-def shell_command(cmdstrs):
+def shell_command(cmdstrs,timeout):
# cmdresult = re.split(r'\s+', cmdstrs)
# print(cmdresult)
result = default_result()
result['return_info'] = ''
shell_start_time = time.time()
child = Popen(cmdstrs, shell=True, stdout=PIPE, stderr=PIPE)
+ if timeout:
+ while child.poll() is None:
+ time.sleep(0.2)
+ now = time.time()
+ if int(now - shell_start_time) > timeout:
+ os.kill(child.pid, signal.SIGKILL)
+ os.waitpid(-1, os.WNOHANG)
+ result['exit_code']=126
+ return result
+
out, err = child.communicate()
shell_end_time = time.time()
result['shell_run_time'] = shell_end_time - shell_start_time
diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py
index 80021c8..5790d75 100644
--- a/fir_ser/api/utils/app/supersignutils.py
+++ b/fir_ser/api/utils/app/supersignutils.py
@@ -7,9 +7,11 @@
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
+from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo,Apps,APPToDeveloper
from api.utils.app.randomstrings import make_app_uuid, make_from_user_uuid
from django.db.models import F
+from api.utils.storage.storage import Storage
+from api.utils.storage.caches import del_cache_response_by_short
def udid_bytes_to_dict(xml_stream):
@@ -123,7 +125,7 @@ class IosUtils(object):
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()
- if usedeviceobj and usedeviceobj.developer_obj.use_number < usedeviceobj.developer_obj.usable_number:
+ if usedeviceobj and usedeviceobj.developerid.use_number < usedeviceobj.developerid.usable_number:
developer_obj = usedeviceobj.developerid
else:
developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, is_actived=True,
@@ -134,7 +136,7 @@ class IosUtils(object):
def create_cert(self):
app_api_obj = AppDeveloperApi(**self.auth)
app_api_obj.create_cert(self.user_obj)
- file_format_path_name = self.file_format_path()
+ file_format_path_name = file_format_path(self.user_obj,self.auth)
cert_info = None
try:
with open(file_format_path_name + '.info', "r") as f:
@@ -142,9 +144,10 @@ class IosUtils(object):
except Exception as e:
print(e)
cert_id = re.findall(r'.*\n\tid=(.*),.*', cert_info)[0].replace('"', '')
- AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, email=self.auth.get("username")).first().update(
- is_actived=True, certid=cert_id)
-
+ developer_obj=AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, email=self.auth.get("username")).first()
+ developer_obj.is_actived=True
+ developer_obj.certid=cert_id
+ developer_obj.save()
def download_profile(self):
app_api_obj = AppDeveloperApi(**self.auth)
bundleId = self.app_obj.bundle_id
@@ -153,13 +156,13 @@ class IosUtils(object):
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 file_format_path(self):
- 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)
- return file_format_path_name
+ # def file_format_path(self):
+ # 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)
+ # return file_format_path_name
def get_profile_full_path(self):
cert_dir_name = make_app_uuid(self.user_obj, self.auth.get("username"))
@@ -171,10 +174,11 @@ class IosUtils(object):
def resign(self):
if AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).first().is_signed:
- return
+ if APPToDeveloper.objects.filter(app_id=self.app_obj).first():
+ return
self.download_profile()
- file_format_path_name = self.file_format_path()
+ file_format_path_name = file_format_path(self.user_obj,self.auth)
my_local_key = file_format_path_name + ".key"
app_dev_pem = file_format_path_name + ".pem"
ResignAppObj = ResignApp(my_local_key, app_dev_pem)
@@ -191,15 +195,36 @@ class IosUtils(object):
"is_signed": True,
"binary_file": random_file_name
}
+ #更新已经完成签名状态,设备消耗记录,和开发者已消耗数量
AppUDID.objects.filter(app_id=self.app_obj, udid=self.udid_info.get('udid')).update(**newdata)
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())
- AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, is_actived=True,
- use_number__lte=F("usable_number")).first().update(
- use_number=self.developer_obj.use_number + 1)
+ developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=self.user_obj, is_actived=True,
+ use_number__lte=F("usable_number")).first()
+ developer_obj.use_number=self.developer_obj.use_number + 1
+ developer_obj.save()
+
+ # 生成新的ipa,然后替换release,或许,binary_file 这个字段已经无用
+ # AppReleaseInfo.objects.filter(app_id=self.app_obj,is_master=True).update(release_id=random_file_name)
+
+ del_cache_response_by_short(self.app_obj.short,self.app_obj.app_id,udid=self.udid_info.get('udid'))
+
+
+ #创建
+ apptodev_obj=APPToDeveloper.objects.filter(developerid=developer_obj,app_id=self.app_obj).first()
+ if apptodev_obj:
+ storage = Storage(self.user_obj)
+ storage.delete_file(apptodev_obj.binary_file, release_obj.release_type)
+
+ apptodev_obj.binary_file=random_file_name
+ apptodev_obj.save()
+
+ else:
+ APPToDeveloper.objects.create(developerid=developer_obj,app_id=self.app_obj,binary_file=random_file_name)
@staticmethod
def disable_udid(udid_obj,app_id):
+
usedeviceobj=APPSuperSignUsedInfo.objects.filter(udid=udid_obj,app_id_id=app_id)
if usedeviceobj:
developer_obj = usedeviceobj.first().developerid
@@ -208,6 +233,153 @@ class IosUtils(object):
"password": developer_obj.password,
"certid": developer_obj.certid
}
+
+ # 需要判断该设备在同一个账户下 的多个应用,若存在,则不操作
+ udid_lists=APPSuperSignUsedInfo.objects.values_list("udid__udid").filter(developerid=developer_obj)
+ if len(udid_lists) == len(set(udid_lists)):
+ app_api_obj = AppDeveloperApi(**auth)
+ app_api_obj.set_device_status("disable",udid_obj.udid)
+
+ if developer_obj.use_number > 0:
+ developer_obj.use_number=developer_obj.use_number-1
+ developer_obj.save()
+
+ usedeviceobj.delete()
+
+ # 通过开发者id判断 app_id 是否多个,否则删除profile 文件
+ if APPSuperSignUsedInfo.objects.filter(developerid=developer_obj, app_id_id=app_id).count() == 0:
+ app_api_obj = AppDeveloperApi(**auth)
+ app_obj = Apps.objects.filter(pk=app_id).first()
+ app_api_obj.del_profile(app_obj.bundle_id,app_obj.app_id)
+ app_api_obj2 = AppDeveloperApi(**auth)
+ app_api_obj2.del_app(app_obj.bundle_id,app_obj.app_id)
+
+ APPToDeveloper.objects.filter(developerid=developer_obj,app_id_id=app_id).delete()
+
+ @staticmethod
+ def clean_udid_by_app_obj(app_obj):
+ for SuperSignUsed_obj in APPSuperSignUsedInfo.objects.filter(app_id=app_obj):
+ udid_obj = SuperSignUsed_obj.udid
+ developer_obj=SuperSignUsed_obj.developerid
+
+ auth = {
+ "username": developer_obj.email,
+ "password": developer_obj.password,
+ "certid": developer_obj.certid
+ }
+
+ # 需要判断该设备在同一个账户下 的多个应用,若存在,则不操作
+ udid_lists = APPSuperSignUsedInfo.objects.values_list("udid__udid").filter(developerid=developer_obj)
+ if len(udid_lists) == len(set(udid_lists)):
+ app_api_obj = AppDeveloperApi(**auth)
+ app_api_obj.set_device_status("disable", udid_obj.udid)
+
+ if developer_obj.use_number > 0:
+ developer_obj.use_number = developer_obj.use_number - 1
+ developer_obj.save()
+
+ udid_obj.delete()
+
+ SuperSignUsed_obj.delete()
+
+
+
+ @staticmethod
+ def clean_app_by_user_obj(app_obj,user_obj):
+ '''
+ 该APP为超级签,删除app的时候,需要清理一下开发者账户里面的profile 和 bundleid
+ :param app_obj:
+ :param user_obj:
+ :return:
+ '''
+ 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:
+ IosUtils.clean_app_by_developer_obj(app_obj,developer_obj)
+ APPToDeveloper.objects.filter(developerid=developer_obj,app_id=app_obj).delete()
+
+ IosUtils.clean_udid_by_app_obj(app_obj)
+ @staticmethod
+ def clean_app_by_developer_obj(app_obj,developer_obj):
+ auth = {
+ "username": developer_obj.email,
+ "password": developer_obj.password,
+ "certid": developer_obj.certid
+ }
+ app_api_obj = AppDeveloperApi(**auth)
+ app_api_obj.del_profile(app_obj.bundle_id, app_obj.app_id)
+ app_api_obj2 = AppDeveloperApi(**auth)
+ app_api_obj2.del_app(app_obj.bundle_id,app_obj.app_id)
+
+ @staticmethod
+ def clean_developer(developer_obj):
+ '''
+ 根据消耗记录 删除该苹果账户下所有信息
+ :param developer_obj:
+ :return:
+ '''
+ auth = {
+ "username": developer_obj.email,
+ "password": developer_obj.password,
+ "certid": developer_obj.certid
+ }
+ for SuperSignUsed_obj in APPSuperSignUsedInfo.objects.filter(developerid=developer_obj):
+ app_obj = SuperSignUsed_obj.app_id
app_api_obj = AppDeveloperApi(**auth)
- app_api_obj.set_device_status("disable",udid_obj.udid)
- usedeviceobj.delete()
\ No newline at end of file
+ app_api_obj.del_profile(app_obj.bundle_id, app_obj.app_id)
+ app_api_obj2 = AppDeveloperApi(**auth)
+ app_api_obj2.del_app(app_obj.bundle_id,app_obj.app_id)
+ APPToDeveloper.objects.filter(developerid=developer_obj, app_id=app_obj).delete()
+
+ @staticmethod
+ def active_developer(developer_obj,code=None):
+ '''
+ 激活开发者账户
+ :param developer_obj:
+ :param code:
+ :return:
+ '''
+ auth = {
+ "username": developer_obj.email,
+ "password": developer_obj.password,
+ "certid": developer_obj.certid
+ }
+ app_api_obj = AppDeveloperApi(**auth)
+ return app_api_obj.active(code)
+
+ @staticmethod
+ def create_developer_cert(developer_obj,user_obj):
+ auth = {
+ "username": developer_obj.email,
+ "password": developer_obj.password,
+ "certid": developer_obj.certid
+ }
+ app_api_obj = AppDeveloperApi(**auth)
+ app_api_obj.create_cert(user_obj)
+ file_format_path_name = file_format_path(user_obj,auth)
+ cert_info = None
+ try:
+ with open(file_format_path_name + '.info', "r") as f:
+ cert_info = f.read()
+ except Exception as e:
+ print(e)
+ cert_id = re.findall(r'.*\n\tid=(.*),.*', cert_info)[0].replace('"', '')
+ developer_obj=AppIOSDeveloperInfo.objects.filter(user_id=user_obj, email=auth.get("username")).first()
+ developer_obj.is_actived=True
+ developer_obj.certid=cert_id
+ developer_obj.save()
+
+
+
+
+def file_format_path(user_obj,auth):
+ cert_dir_name = make_app_uuid(user_obj, 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)
+ return file_format_path_name
+
+
+
diff --git a/fir_ser/api/utils/crontab/runWin.py b/fir_ser/api/utils/crontab/runWin.py
new file mode 100644
index 0000000..960a1fd
--- /dev/null
+++ b/fir_ser/api/utils/crontab/runWin.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+# project: 4月
+# author: liuyu
+# date: 2020/4/7
+
+from apscheduler.schedulers.background import BackgroundScheduler
+from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job
+from fir_ser.settings import SYNC_CACHE_TO_DATABASE
+from api.utils.crontab.sync_cache import sync_download_times
+
+# import atexit
+# import fcntl
+#
+# # 主要是为了防止多进程出现的多个定时任务同时执行
+# f = open("scheduler.lock", "wb")
+# try:
+# fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+
+# 开启定时工作
+try:
+ # 实例化调度器
+ scheduler = BackgroundScheduler()
+ # 调度器使用DjangoJobStore()
+ scheduler.add_jobstore(DjangoJobStore(), "default")
+
+
+ # 设置定时任务,选择方式为interval,时间间隔为10s
+ # 另一种方式为每天固定时间执行任务,对应代码为:
+ # @register_job(scheduler, 'cron', day_of_week='mon-fri', hour='9', minute='30', second='10',id='task_time')
+ @register_job(scheduler, "interval", seconds=SYNC_CACHE_TO_DATABASE.get("download_times"))
+ def sync_download_times_job():
+ # 这里写你要执行的任务
+ sync_download_times()
+
+
+ register_events(scheduler)
+ scheduler.start()
+except Exception as e:
+ print(e)
+ # 有错误就停止定时器
+ scheduler.shutdown()
+#
+# except:
+# pass
+#
+#
+# def unlock():
+# fcntl.flock(f, fcntl.LOCK_UN)
+# f.close()
+#
+#
+# atexit.register(unlock)
diff --git a/fir_ser/api/utils/serializer.py b/fir_ser/api/utils/serializer.py
index 363b016..5d1772c 100644
--- a/fir_ser/api/utils/serializer.py
+++ b/fir_ser/api/utils/serializer.py
@@ -171,7 +171,7 @@ class AppReleaseSerializer(serializers.ModelSerializer):
icon_url=""
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(obj.icon_url))
+ icon_url = storage.get_download_url(os.path.basename(obj.icon_url),600)
return icon_url
@@ -217,7 +217,7 @@ class DeveloperSerializer(serializers.ModelSerializer):
class Meta:
model = models.AppIOSDeveloperInfo
# depth = 1
- exclude = ["password", "id","name","user_id"]
+ exclude = ["password", "id","user_id"]
class SuperSignUsedSerializer(serializers.ModelSerializer):
class Meta:
diff --git a/fir_ser/api/utils/storage/caches.py b/fir_ser/api/utils/storage/caches.py
index c8553b4..f1ef73a 100644
--- a/fir_ser/api/utils/storage/caches.py
+++ b/fir_ser/api/utils/storage/caches.py
@@ -5,7 +5,7 @@
# date: 2020/4/7
from django.core.cache import cache
-from api.models import Apps,UserInfo,AppReleaseInfo,AppUDID
+from api.models import Apps,UserInfo,AppReleaseInfo,AppUDID,APPToDeveloper,APPSuperSignUsedInfo
import time,os
from django.utils import timezone
from fir_ser.settings import CACHE_KEY_TEMPLATE
@@ -24,8 +24,19 @@ 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:
- filename=appudid_obj.binary_file+'.ipa'
- return local_storage.get_download_url(filename, limit)
+ 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()
+ if APPToDeveloper_obj:
+ filename=APPToDeveloper_obj.binary_file
+ return local_storage.get_download_url(filename, limit, download_url_type)
+ else:
+ return ""
+ else:
+ return ""
+ else:
+ return ""
+
return local_storage.get_download_url(filename, limit, download_url_type)
down_key = "_".join([key.lower(), CACHE_KEY_TEMPLATE.get('download_url_key'), filename])
download_val = cache.get(down_key)
@@ -38,7 +49,9 @@ def get_download_url_by_cache(app_obj, filename, limit, isdownload=True,key='',u
return storage.get_download_url(filename, limit)
-def get_app_instance_by_cache(app_id,password, limit):
+def get_app_instance_by_cache(app_id,password, limit,udid):
+ if udid:
+ return Apps.objects.filter(app_id=app_id).values("pk", 'user_id', 'type','password','issupersign').first()
app_key="_".join([CACHE_KEY_TEMPLATE.get("app_instance_key"),app_id])
app_obj_cache = cache.get(app_key)
if not app_obj_cache:
@@ -79,10 +92,11 @@ def del_cache_response_by_short(short,app_id,udid=''):
key='ShortDownloadView'.lower()
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")),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]))
+ 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]))
def del_cache_by_app_id(app_id,user_obj):
diff --git a/fir_ser/api/views/apps.py b/fir_ser/api/views/apps.py
index 9d20adb..261f81c 100644
--- a/fir_ser/api/views/apps.py
+++ b/fir_ser/api/views/apps.py
@@ -11,10 +11,11 @@ from rest_framework.response import Response
from django.db.models import Sum
import os
from fir_ser import settings
+from api.utils.app.supersignutils import IosUtils
from api.utils.app.randomstrings import make_from_user_uuid
from api.utils.storage.storage import Storage
from api.utils.storage.caches import del_cache_response_by_short,get_app_today_download_times
-from api.models import Apps, AppReleaseInfo
+from api.models import Apps, AppReleaseInfo,APPToDeveloper
from api.utils.serializer import AppsSerializer, AppReleaseSerializer, UserInfoSerializer
from rest_framework.pagination import PageNumberPagination
@@ -107,6 +108,9 @@ class AppInfoView(APIView):
userserializer = UserInfoSerializer(request.user)
res.userinfo = {}
res.userinfo = userserializer.data
+ count=APPToDeveloper.objects.filter(app_id=apps_obj).count()
+ res.data["count"] = count
+
return Response(res.dict)
def delete(self, request, app_id):
@@ -115,18 +119,16 @@ class AppInfoView(APIView):
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
if apps_obj:
storage = Storage(request.user)
- for appreleaseobj in AppReleaseInfo.objects.filter(app_id=apps_obj).all():
- storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
- storage.delete_file(appreleaseobj.icon_url)
- appreleaseobj.delete()
-
has_combo = apps_obj.has_combo
if has_combo:
del_cache_response_by_short(apps_obj.has_combo.short,apps_obj.has_combo.app_id)
apps_obj.has_combo.has_combo = None
-
- apps_obj.delete()
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
+ for appreleaseobj in AppReleaseInfo.objects.filter(app_id=apps_obj).all():
+ storage.delete_file(appreleaseobj.release_id, appreleaseobj.release_type)
+ storage.delete_file(appreleaseobj.icon_url)
+ appreleaseobj.delete()
+ apps_obj.delete()
return Response(res.dict)
@@ -135,6 +137,12 @@ class AppInfoView(APIView):
if app_id:
data = request.data
+ clean = data.get("clean",None)
+ if clean :
+ apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
+ IosUtils.clean_app_by_user_obj(apps_obj,request.user)
+ return Response(res.dict)
+
has_combo = data.get("has_combo", None)
if has_combo:
actions = has_combo.get("action", None)
@@ -309,7 +317,6 @@ class AppReleaseinfoView(APIView):
else:
binary_url = appreleaseobj.first().binary_url
- print(binary_url)
appreleaseobj.update(**{"binary_url": binary_url})
except Exception as e:
diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py
index c2935e3..23ec80b 100644
--- a/fir_ser/api/views/download.py
+++ b/fir_ser/api/views/download.py
@@ -106,7 +106,13 @@ class ShortDownloadView(APIView):
def calculate_cache_key(self, view_instance, view_method,
request, args, kwargs):
release_id = request.query_params.get("release_id", '')
- udid = request.query_params.get("udid", '')
+ udid = request.query_params.get("udid", None)
+ time = request.query_params.get("time", None)
+ if udid and time:
+ udid=time
+ if not udid:
+ udid=""
+
return "_".join([settings.CACHE_KEY_TEMPLATE.get("download_short_key"), kwargs.get("short", ''),release_id,udid])
class InstallView(APIView):
@@ -130,9 +136,8 @@ class InstallView(APIView):
dtoken = DownloadToken()
if dtoken.verify_token(downtoken,release_id):
- app_obj = get_app_instance_by_cache(app_id,password,900)
+ app_obj = get_app_instance_by_cache(app_id,password,900,udid)
if app_obj:
- set_app_download_by_cache(app_id)
if app_obj.get("type") == 0:
apptype = '.apk'
download_url = get_download_url_by_cache(app_obj,release_id + apptype,600)
@@ -144,6 +149,8 @@ class InstallView(APIView):
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!= "":
+ set_app_download_by_cache(app_id)
return Response(res.dict)
else:
res.code = 1004
diff --git a/fir_ser/api/views/login.py b/fir_ser/api/views/login.py
index 68c5693..f6fdbdc 100644
--- a/fir_ser/api/views/login.py
+++ b/fir_ser/api/views/login.py
@@ -32,6 +32,7 @@ class LoginView(APIView):
username = receive.get("username")
password = receive.get("password")
user = auth.authenticate(username=username, password=password)
+ print(username,password,user)
if user is not None:
if user.is_active:
diff --git a/fir_ser/api/views/supersign.py b/fir_ser/api/views/supersign.py
index 2af0c46..8ff7093 100644
--- a/fir_ser/api/views/supersign.py
+++ b/fir_ser/api/views/supersign.py
@@ -35,15 +35,73 @@ class DeveloperView(APIView):
app_page_serializer = page_obj.paginate_queryset(queryset=developer_obj.order_by("-updated_time"), request=request,
view=self)
- app_serializer = DeveloperSerializer(app_page_serializer, many=True,)
+ Developer_serializer = DeveloperSerializer(app_page_serializer, many=True,)
userserializer = UserInfoSerializer(request.user)
res.userinfo = {}
res.has_next = {}
res.userinfo = userserializer.data
- res.data = app_serializer.data
+ res.data = Developer_serializer.data
res.has_next = page_obj.page.has_next()
return Response(res.dict)
+ def put(self,request):
+ data = request.data
+ email=data.get("email",None)
+ if email:
+ developer_obj = AppIOSDeveloperInfo.objects.filter(user_id=request.user,email=email).first()
+
+
+
+ if developer_obj:
+ act = data.get("act", None)
+ if act:
+ res = BaseResponse()
+ if act == "preactive":
+ if not IosUtils.active_developer(developer_obj):
+ res.code = 1008
+ res.msg = "开发者账户或密码有误"
+ return Response(res.dict)
+ else:
+ res.code = 1009
+ return Response(res.dict)
+ elif act == "nowactive" :
+ code = data.get("code", None)
+ if code:
+ if IosUtils.active_developer(developer_obj,code):
+ developer_obj.is_actived=True
+ developer_obj.save()
+ IosUtils.create_developer_cert(developer_obj,request.user)
+ else:
+ developer_obj.usable_number=data.get("usable_number",developer_obj.usable_number)
+ developer_obj.description = data.get("description", developer_obj.description)
+ password = data.get("password", developer_obj.password)
+ if password != "" and password != developer_obj.password:
+ developer_obj.password=password
+ developer_obj.is_actived=False
+ developer_obj.save()
+
+ return self.get(request)
+
+ def post(self,request):
+ data = request.data
+ datainfo={
+ "usable_number" : data.get("usable_number", ""),
+ "description" : data.get("description", ""),
+ "password" : data.get("password", ""),
+ "email" : data.get("email", ""),
+ }
+ try:
+ AppIOSDeveloperInfo.objects.create(user_id=request.user,**datainfo)
+ except Exception as e:
+ print(e)
+ res = BaseResponse()
+ res.code=1005
+ res.msg="添加失败"
+ return Response(res.dict)
+
+ return self.get(request)
+
+
class SuperSignUsedView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
@@ -84,7 +142,6 @@ class AppUDIDUsedView(APIView):
return Response(res.dict)
def delete(self,request):
- res = BaseResponse()
id = request.query_params.get("id", None)
app_id = request.query_params.get("aid", None)
app_udid_obj=AppUDID.objects.filter(app_id__user_id_id=request.user,pk=id)
diff --git a/fir_ser/fir_ser/urls.py b/fir_ser/fir_ser/urls.py
index c24230b..36ea8b4 100644
--- a/fir_ser/fir_ser/urls.py
+++ b/fir_ser/fir_ser/urls.py
@@ -33,6 +33,8 @@ from api.views.captcha import CaptchaView
from django.views.static import serve
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),
@@ -49,4 +51,5 @@ urlpatterns = [
re_path(r'files/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
re_path("download/(?P\w+\.\w+)$", DownloadView.as_view(),name="download"),
re_path("install/(?P\w+)$", InstallView.as_view(), name="install"),
+ re_path("^udid/(?P\w+)$", IosUDIDView.as_view()),
]
diff --git a/fir_ser/requirements.txt b/fir_ser/requirements.txt
index c0e28aa..38da2b3 100644
--- a/fir_ser/requirements.txt
+++ b/fir_ser/requirements.txt
@@ -7,11 +7,14 @@ APScheduler==3.6.3
asgiref==3.2.3
asn1crypto==1.3.0
backcall==0.1.0
+bcrypt==3.1.7
certifi==2019.11.28
+cffi==1.14.0
chardet==3.0.4
Click==7.0
colorama==0.4.3
crcmod==1.7
+cryptography==2.9.2
cycler==0.10.0
decorator==4.4.2
Django==3.0.3
@@ -35,16 +38,19 @@ mysqlclient==1.4.6
networkx==2.4
numpy==1.18.1
oss2==2.9.1
+paramiko==2.7.1
parso==0.6.2
pexpect==4.8.0
pickleshare==0.7.5
Pillow==7.0.0
prompt-toolkit==3.0.3
ptyprocess==0.6.0
+pycparser==2.20
pycryptodome==3.9.7
pydot==1.4.1
Pygments==2.5.2
PyMySQL==0.9.3
+PyNaCl==1.3.0
pyparsing==2.4.6
python-dateutil==2.8.1
pytz==2019.3
diff --git a/fir_ser/supersign/scripts/apple_api.rb b/fir_ser/supersign/scripts/apple_api.rb
index bb25a19..29503c2 100644
--- a/fir_ser/supersign/scripts/apple_api.rb
+++ b/fir_ser/supersign/scripts/apple_api.rb
@@ -50,11 +50,18 @@ class DevelopPortalHandle
profile = nil
if 0 < filtered_profiles.length then
profile = filtered_profiles[0]
+ all_devices = Spaceship::Portal.device.all
+ profile.devices=all_devices
+ profile.update!
+ profile = provisioningClass.find_by_bundle_id(bundle_id: appid)[0]
elsif 0 == filtered_profiles.length then
profile = createDistributionProvision(provisioningClass,appid,provisionName,certid)
end
- #没有找到就创建,找到就下载
+ if profile.status == "Invalid" or profile.status == "Expired" then
+ profile.repair! # yes, that's all you need to repair a profile
+ end
+
File.write(provisionName, profile.download)
return provisionName
end
@@ -150,6 +157,8 @@ end
handle.createCert(file_format_path_name)
end
+ when "active"
+ puts "active"
else
puts "error"
end