add api cli

super_sign_new
youngS 4 years ago
parent 1683f27792
commit d5c42cc769
  1. 4
      fir_client/src/components/FirApps.vue
  2. 44
      fir_client/src/components/FirHeader.vue
  3. 2
      fir_client/src/components/FirLogin.vue
  4. 1
      fir_client/src/restful/download.js
  5. 14
      fir_client/src/restful/index.js
  6. 18
      fir_ser/api/migrations/0008_auto_20200922_1951.py
  7. 28
      fir_ser/api/migrations/0009_auto_20200925_2041.py
  8. 18
      fir_ser/api/migrations/0010_userinfo_api_token.py
  9. 4
      fir_ser/api/models.py
  10. 4
      fir_ser/api/urls.py
  11. 36
      fir_ser/api/utils/auth.py
  12. 2
      fir_ser/api/utils/response.py
  13. 7
      fir_ser/api/views/apps.py
  14. 24
      fir_ser/api/views/login.py
  15. 6
      fir_ser/api/views/uploads.py
  16. 267
      fir_ser/cli.py
  17. 0
      fir_ser/cli/__init__.py
  18. 5
      fir_ser/cli/apps.py
  19. 29
      fir_ser/cli/urls.py
  20. 23
      fir_ser/cli/views/apps.py
  21. 25
      fir_ser/cli/views/login.py
  22. 17
      fir_ser/cli/views/uploads.py
  23. 18
      fir_ser/fir_ser/urls.py

@ -196,10 +196,6 @@
</el-col>
</el-row>
</el-col>
<!-- <el-col :span="1" class="surplus-card">-->
<!-- -->
<!-- </el-col>-->
<el-col :span="8" class="surplus-card">
<el-row>
<el-col :span="8">

@ -1,6 +1,23 @@
<template>
<div>
<el-container class="navbar-wrapper">
<el-dialog
title="API Token"
:visible.sync="dialogVisible"
width="30%"
center
>
<span>可用于调用公开 API可用于登录 fly-cli请勿泄露您的 token</span>
<el-main>
<el-link type="primary" v-if="token" :underline="false">{{ token }}</el-link>
</el-main>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="maketoken">重新生成</el-button>
</span>
</el-dialog>
<el-row :gutter="20">
<el-col :span="14" style="padding-top: 16px;margin-left: 60px">
@ -27,6 +44,7 @@
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="userinfo">个人资料</el-dropdown-item>
<el-dropdown-item command="chpasswd">修改密码</el-dropdown-item>
<el-dropdown-item command="apitoken">API token</el-dropdown-item>
<el-dropdown-item command="storage" v-if="$store.state.userinfo.storage_active">存储管理
</el-dropdown-item>
<el-dropdown-item command="supersign" v-if="$store.state.userinfo.supersign_active">超级签名
@ -48,7 +66,8 @@
</template>
<script>
import {logout} from '../restful'
// eslint-disable-next-line no-unused-vars
import {logout, apitoken} from '../restful'
export default {
name: "FirHeader",
@ -56,8 +75,21 @@
return {
current_user: {},
appName: '',
token:'',
dialogVisible:false
}
}, methods: {
maketoken(){
apitoken(data=>{
if (data.code === 1000) {
this.token = data.data.token;
this.$message({
type: 'success',
message: '重新生成成功!'
});
}
},{methods: 'PUT',token:this.token});
},
handleCommand(command) {
if (command === 'userinfo') {
this.$router.push({name: 'FirUserProfileInfo'})
@ -68,6 +100,16 @@
} else if (command === 'supersign') {
this.$store.dispatch('doucurrentapp', {});
this.$router.push({"name": 'FirSuperSignBase', params: {act: "iosdeveloper"}})
}
else if (command === 'apitoken'){
this.dialogVisible=true;
apitoken(data=>{
if (data.code === 1000) {
this.token = data.data.token;
}
},{methods: 'GET',token:this.token});
} else if (command === 'exit') {
logout(data => {

@ -133,7 +133,7 @@
if (password.length > 6) {
loginFun(data => {
if (data.code == 1000) {
if (data.code === 1000) {
this.$message({
message: '登录成功',
type: 'success'

@ -6,7 +6,6 @@ Axios.defaults.withCredentials = true;
// keepAlive: true
// });
// const DOMAIN = 'https://fly.harmonygames.cn';
const DOMAIN = window.g.baseUrl;
const APIPATH = '/api/v1/fir/server';
let USERSEVER = DOMAIN + APIPATH;

@ -236,6 +236,20 @@ export function logout(callBack, params, load = true) {
);
}
/**api token */
export function apitoken(callBack, params, load = true) {
getData(
params.methods,
USERSEVER + '/token',
params,
data => {
callBack(data);
},
load,
true,
true
);
}
/**用户应用列表 */
export function getapps(callBack, params, load = true) {

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-09-22 19:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0007_auto_20200520_1153'),
]
operations = [
migrations.AlterField(
model_name='userinfo',
name='domain_name',
field=models.CharField(blank=True, max_length=64, null=True, verbose_name='下载页面域名'),
),
]

@ -0,0 +1,28 @@
# Generated by Django 3.0.3 on 2020-09-25 20:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0008_auto_20200922_1951'),
]
operations = [
migrations.AddField(
model_name='userinfo',
name='storage_active',
field=models.BooleanField(default=False, verbose_name='配置存储,默认关闭'),
),
migrations.AddField(
model_name='userinfo',
name='supersign_active',
field=models.BooleanField(default=False, verbose_name='配置超级签,默认关闭'),
),
migrations.AlterField(
model_name='userinfo',
name='download_times',
field=models.IntegerField(default=100, verbose_name='可用下载次数'),
),
]

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2021-01-07 18:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0009_auto_20200925_2041'),
]
operations = [
migrations.AddField(
model_name='userinfo',
name='api_token',
field=models.CharField(default='', max_length=256, verbose_name='api访问密钥'),
),
]

@ -5,6 +5,7 @@ from django.db import models
from django.contrib.contenttypes.models import ContentType
from api.utils.app.randomstrings import make_random_uuid
from django.contrib.auth.models import AbstractUser
from api.utils.TokenManager import generateAlphanumericTokenOfLength
######################################## 用户表 ########################################
@ -44,6 +45,7 @@ class UserInfo(AbstractUser):
history_release_limit = models.IntegerField(default=10, verbose_name="app 历史记录版本", blank=True, null=True)
storage = models.OneToOneField(to='AppStorage', related_name='app_storage',
on_delete=models.SET_NULL, verbose_name="存储", null=True, blank=True)
api_token = models.CharField(max_length=256, verbose_name='api访问密钥', default='')
class Meta:
verbose_name = '账户信息'
@ -55,6 +57,8 @@ class UserInfo(AbstractUser):
def save(self, *args, **kwargs):
if len(self.uid) < 8:
self.uid = make_random_uuid()
if len(self.api_token) < 8:
self.api_token = self.uid+generateAlphanumericTokenOfLength(64)
super(UserInfo, self).save(*args, **kwargs)

@ -13,10 +13,9 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path, include
from api.views.login import LoginView, UserInfoView, RegistView, AuthorizationView, ChangeAuthorizationView
from api.views.login import LoginView, UserInfoView, RegistView, AuthorizationView, ChangeAuthorizationView, UserApiTokenView
from api.views.logout import LogoutView
from api.views.apps import AppsView, AppInfoView, AppReleaseinfoView
from api.views.download import ShortDownloadView
@ -42,6 +41,7 @@ urlpatterns = [
re_path("^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", AppReleaseinfoView.as_view()),
re_path("^upload$", UploadView.as_view()),
re_path("^userinfo", UserInfoView.as_view()),
re_path("^token", UserApiTokenView.as_view()),
re_path("^short/(?P<short>\w+)$", ShortDownloadView.as_view()),
re_path("^udid/(?P<short>\w+)$", IosUDIDView.as_view()),
re_path("^analyse$", AppAnalyseView.as_view()),

@ -1,3 +1,8 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 9月
# author: NinEveN
# date: 2020/9/24
from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
@ -7,15 +12,28 @@ from fir_ser.settings import CACHE_KEY_TEMPLATE
import base64
def get_user_from_auth(request):
def get_user_from_api_token(request):
if request.method == "OPTIONS":
return None
api_token = request.META.get("HTTP_APIAUTHORIZATION", request.query_params.get("api_token", None))
user_obj = UserInfo.objects.filter(api_token=api_token).first()
if not user_obj:
raise AuthenticationFailed({"code": 1001, "error": "无效的api_token"})
if user_obj.is_active:
return user_obj, api_token
else:
raise AuthenticationFailed({"code": 1001, "error": "用户被禁用"})
def get_user_from_request_auth(request):
if request.method == "OPTIONS":
return None
request_token = request.META.get("HTTP_AUTHORIZATION", request.query_params.get("token", None))
if request_token:
try:
format_token = base64.b64decode(request_token).decode()
auth_token = format_token.split(":")[0]
user_name = format_token.split(":")[1]
except Exception:
raise AuthenticationFailed({"code": 1001, "error": "token不合法"})
@ -41,19 +59,27 @@ def get_user_from_auth(request):
return user_obj, auth_token
else:
raise AuthenticationFailed({"code": 1001, "error": "用户被禁用"})
else:
raise AuthenticationFailed({"code": 1001, "error": "无效的认证"})
class ExpiringTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
return get_user_from_auth(request)
return get_user_from_request_auth(request)
class ApiTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
return get_user_from_api_token(request)
class StoragePermission(BasePermission):
message = "权限不足"
def has_permission(self, request, view):
results = get_user_from_auth(request)
results = get_user_from_request_auth(request)
if results and results[0]:
return results[0].storage_active
return True
@ -63,7 +89,7 @@ class SuperSignPermission(BasePermission):
message = "权限不足"
def has_permission(self, request, view):
results = get_user_from_auth(request)
results = get_user_from_request_auth(request)
if results and results[0]:
return results[0].supersign_active
return True

@ -1,7 +1,7 @@
class BaseResponse(object):
def __init__(self):
self.code = 1000
self.msg = ""
self.msg = "success"
self.data = None
@property

@ -35,10 +35,9 @@ class AppsView(APIView):
app_type = request.query_params.get("type", None)
act_type = request.query_params.get("act", None)
res = BaseResponse()
res.hdata = {"all_hits_count": 0}
res.hdata["upload_domain"] = request.user.domain_name
res.hdata["ios_count"] = Apps.objects.filter(type=1, user_id=request.user).values('app_id').count()
res.hdata["android_count"] = Apps.objects.filter(type=0, user_id=request.user).values('app_id').count()
res.hdata = {"all_hits_count": 0, "upload_domain": request.user.domain_name,
"ios_count": Apps.objects.filter(type=1, user_id=request.user).values('app_id').count(),
"android_count": Apps.objects.filter(type=0, user_id=request.user).values('app_id').count()}
android_app_ids = Apps.objects.filter(**{"user_id": request.user, "type": 0}).values('app_id')
res.hdata["android_today_hits_count"] = get_app_today_download_times(android_app_ids)

@ -487,3 +487,27 @@ class ChangeAuthorizationView(APIView):
res = CheckChangeUerinfo(target, act, 'change', request.user)
return Response(res.dict)
class UserApiTokenView(APIView):
authentication_classes = [ExpiringTokenAuthentication, ]
def get(self, request):
res = BaseResponse()
res.data = {
'token': request.user.api_token
}
return Response(res.dict)
def put(self, request):
res = BaseResponse()
data = request.data
oldtoken = data.get("token", None)
if oldtoken == request.user.api_token:
request.user.api_token = 'reset'
try:
request.user.save()
except Exception as e:
logger.error("User %s api_token save failed. Excepiton:%s" % (request.user, e))
return self.get(request)

@ -37,7 +37,7 @@ class AppAnalyseView(APIView):
if bundleid and app_type:
ap = 'apk'
if app_type == 'iOS':
if app_type.lower() == 'iOS'.lower():
ap = 'ipa'
app_uuid = make_app_uuid(request.user, bundleid + ap)
release_id = make_from_user_uuid(request.user)
@ -126,6 +126,8 @@ class AppAnalyseView(APIView):
except Exception as e:
logger.error("user %s %s save app info failed Exception:%s" % (request.user, data.get("bundleid"), e))
res.code = 10003
res.msg = 'save app info failed'
return Response(res.dict)
@ -199,7 +201,7 @@ class UploadView(APIView):
try:
certinfo = json.loads(certinfo)
if not certinfo:
res.msg = "token 校验失败"
res.msg = "数据信息 校验失败"
res.code = 1006
return Response(res.dict)
except Exception as e:

@ -0,0 +1,267 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 1月
# author: NinEveN
# date: 2021/1/9
import os
import sys
import plistlib
import random
import re
import json
import zipfile
from requests_toolbelt import MultipartEncoder
import oss2
import requests
from androguard.core.bytecodes import apk
def upload_aliyunoss(access_key_id, access_key_secret, security_token, endpoint, bucket, file_path, file_name):
stsauth = oss2.StsAuth(access_key_id, access_key_secret, security_token)
bucket = oss2.Bucket(stsauth, endpoint, bucket)
with open(file_path, 'rb') as fileobj:
bucket.put_object(file_name, fileobj)
print("数据上传存储成功.")
def upload_qiniuyunoss(key, token, file_path):
from qiniu import put_file
ret, info = put_file(token, key, file_path)
if info.status_code == 200:
print("数据上传存储成功.")
else:
raise AssertionError(info.text)
class FLY_CLI_SER(object):
def __init__(self, fly_cli_domain, fly_cli_token):
self.fly_cli_domain = fly_cli_domain
self._header = {
"User-Agent": "fly-cli",
"accept": "application/json",
"APIAUTHORIZATION": fly_cli_token
}
def get_upload_token(self, bundleid, type):
url = '%s/api/v2/fir/server/analyse' % self.fly_cli_domain
data = {"bundleid": bundleid, "type": type}
req = requests.post(url, json=data, headers=self._header)
if req.status_code == 200:
if req.json()['code'] == 1000:
return req.json()['data']
raise AssertionError(req.text)
def analyse(self, data):
url = '%s/api/v2/fir/server/analyse' % self.fly_cli_domain
req = requests.put(url, json=data, headers=self._header)
if req.status_code == 200:
if req.json()['code'] == 1000:
print("APP信息更新成功" + req.text)
return
raise AssertionError(req.text)
def upload_local_storage(self, upload_key, upload_token, app_id, file_path):
url = '%s/api/v2/fir/server/upload' % self.fly_cli_domain
m = MultipartEncoder(fields={
'file': (os.path.basename(file_path), open(file_path, 'rb'), 'application/octet-stream'),
'certinfo': json.dumps(
{
'upload_key': upload_key,
'upload_token': upload_token,
'ftype': "app",
'app_id': app_id,
}
),
})
header = {
'Content-Type': m.content_type,
}
req = requests.post(url, data=m, headers={**self._header, **header})
if req.status_code == 200:
if req.json()['code'] == 1000:
print("数据上传存储成功." + req.text)
return
raise AssertionError(req.text)
def upload_app(self, app_path):
appobj = AppInfo(app_path)
appinfo = appobj.get_app_data()
icon_path = appobj.make_app_png()
bundle_id = appinfo.get("bundle_id")
upcretsdata = self.get_upload_token(bundle_id, appinfo.get("type"))
if upcretsdata['storage'] == 1:
# 七牛云存储
upload_qiniuyunoss(upcretsdata['png_key'], upcretsdata['png_token'], icon_path)
upload_qiniuyunoss(upcretsdata['upload_key'], upcretsdata['upload_token'], app_path)
elif upcretsdata['storage'] == 2:
# 阿里云存储
png_auth = upcretsdata['png_token']
upload_aliyunoss(png_auth['access_key_id'], png_auth['access_key_secret'], png_auth['security_token'],
png_auth['endpoint'], png_auth['bucket'], icon_path, upcretsdata['png_key'])
file_auth = upcretsdata['upload_token']
upload_aliyunoss(file_auth['access_key_id'], file_auth['access_key_secret'], file_auth['security_token'],
file_auth['endpoint'], file_auth['bucket'], app_path, upcretsdata['upload_key'])
elif upcretsdata['storage'] == 3:
# 本地存储
self.upload_local_storage(upcretsdata['png_key'], upcretsdata['png_token'], upcretsdata['app_uuid'],
icon_path)
self.upload_local_storage(upcretsdata['upload_key'], upcretsdata['upload_token'], upcretsdata['app_uuid'],
app_path)
app_data = {
"filename": os.path.basename(app_path),
"filesize": os.path.getsize(app_path),
"appname": appinfo['labelname'],
"bundleid": appinfo['bundle_id'],
"version": appinfo['version'],
"buildversion": appinfo['versioncode'],
"miniosversion": appinfo['miniosversion'],
"release_type": appinfo['release_type'],
"release_type_id": 2,
"udid": appinfo.get('udid', []),
"type": appinfo['type'],
}
self.analyse({**app_data, **upcretsdata})
class AppInfo(object):
def __init__(self, app_path):
self.app_path = app_path
self.result = {}
def make_app_png(self):
zf = zipfile.ZipFile(self.app_path)
name_list = zf.namelist()
if self.app_path.endswith("apk"):
pattern = re.compile(r'res/drawable[^/]*/app_icon.png')
elif self.app_path.endswith("ipa"):
pattern = re.compile(r'Payload/[^/]*.app/AppIcon[^/]*[^(ipad)].png')
else:
raise Exception("File type error")
size = 0
iconfile = ""
for path in name_list:
m = pattern.match(path)
if m is not None:
filepath = m.group()
fsize = len(zf.read(filepath))
if size == 0:
iconfile = filepath
if size < fsize:
size = fsize
iconfile = filepath
if size == 0:
raise Exception("File size error")
filename = ''.join(random.sample(
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f',
'e', 'd', 'c', 'b', 'a'], 16))
if not os.path.isdir(os.path.join("tmp", "icon")):
os.makedirs(os.path.join("tmp", "icon"))
with open(os.path.join("tmp", "icon", filename + '.png'), 'wb') as f:
f.write(zf.read(iconfile))
return os.path.join("tmp", "icon", filename + '.png')
def get_app_data(self):
if self.app_path.endswith("apk"):
return self.__get_android_data()
elif self.app_path.endswith("ipa"):
return self.__get_ios_data()
else:
raise Exception("File type error")
def __get_ios_info_path(self, ipaobj):
infopath_re = re.compile(r'Payload/[^/]*.app/Info.plist')
for i in ipaobj.namelist():
m = infopath_re.match(i)
if m is not None:
return m.group()
def __get_android_data(self):
try:
apkobj = apk.APK(self.app_path)
except Exception as err:
raise err
else:
if apkobj.is_valid_APK():
versioncode = apkobj.get_androidversion_code()
bundle_id = apkobj.get_package()
labelname = apkobj.get_app_name()
version = apkobj.get_androidversion_name()
self.result = {
"labelname": labelname,
"bundle_id": bundle_id,
"versioncode": versioncode,
"version": version,
"type": "Android",
"miniosversion": apkobj.get_min_sdk_version()
}
return self.result
def __get_ios_data(self):
if zipfile.is_zipfile(self.app_path):
ipaobj = zipfile.ZipFile(self.app_path)
info_path = self.__get_ios_info_path(ipaobj)
if info_path:
plist_data = ipaobj.read(info_path)
plist_root = plistlib.loads(plist_data)
labelname = plist_root['CFBundleDisplayName']
versioncode = plist_root['CFBundleVersion']
bundle_id = plist_root['CFBundleIdentifier']
version = plist_root['CFBundleShortVersionString']
self.result = {
"labelname": labelname,
"bundle_id": bundle_id,
"versioncode": versioncode,
"version": version,
"type": "iOS",
"miniosversion": plist_root['MinimumOSVersion']
}
release_type_info = self.__get_ios_release_type(ipaobj)
if info_path:
plist_data = ipaobj.read(release_type_info)
if b"ProvisionedDevices" in plist_data:
b = re.findall(rb'<key>ProvisionedDevices</key><array>(.*)</array><key>TeamIdentifier</key>',
plist_data.replace(b'\n', b'').replace(b'\r', b'').replace(b"\t", b""))[0]
clist = re.split(rb'<string>|</string>', b)
nudidlist = []
for x in clist:
if x:
nudidlist.append(x.decode('utf-8'))
self.result["release_type"] = "Adhoc"
self.result['udid'] = nudidlist
else:
self.result["release_type"] = "Inhouse"
self.result["udid"] = []
return self.result
def __get_ios_release_type(self, ipaobj):
infopath_re = re.compile(r'Payload/[^/]*.app/embedded.mobileprovision')
for i in ipaobj.namelist():
m = infopath_re.match(i)
if m is not None:
return m.group()
if __name__ == '__main__':
fly_cli_domain = 'https://fly.harmonygames.cn'
fly_cli_token = '4baf717aff0011ea80c000163e069e27x2gRvmf2035rP3YWITJxvF4VVE32M55AuVHxOvSbTgdwgF54UeXFzrNLkP1lgUID'
fly_obj = FLY_CLI_SER(fly_cli_domain, fly_cli_token)
if len(sys.argv) != 2:
raise ValueError('参数有误')
app_path = sys.argv[1]
if os.path.isfile(app_path):
fly_obj.upload_app(app_path)
raise FileNotFoundError(app_path)

@ -0,0 +1,5 @@
from django.apps import AppConfig
class CliConfig(AppConfig):
name = 'cli'

@ -0,0 +1,29 @@
"""fir_ser URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path, re_path, include
from cli.views.login import CliUserInfoView
from cli.views.apps import CliAppsView, CliAppInfoView, CliAppReleaseinfoView
from cli.views.uploads import CliAppAnalyseView, CliUploadView
urlpatterns = [
re_path("^apps$", CliAppsView.as_view()),
re_path("^apps/(?P<app_id>\w+)", CliAppInfoView.as_view()),
re_path("^appinfos/(?P<app_id>\w+)/(?P<act>\w+)", CliAppReleaseinfoView.as_view()),
re_path("^upload$", CliUploadView.as_view()),
re_path("^userinfo", CliUserInfoView.as_view()),
re_path("^analyse$", CliAppAnalyseView.as_view()),
]

@ -0,0 +1,23 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月
# author: liuyu
# date: 2020/3/4
from api.utils.auth import ApiTokenAuthentication
from api.views.apps import AppsView, AppInfoView, AppReleaseinfoView
import logging
logger = logging.getLogger(__name__)
class CliAppsView(AppsView):
authentication_classes = [ApiTokenAuthentication, ]
class CliAppInfoView(AppInfoView):
authentication_classes = [ApiTokenAuthentication, ]
class CliAppReleaseinfoView(AppReleaseinfoView):
authentication_classes = [ApiTokenAuthentication, ]

@ -0,0 +1,25 @@
from django.contrib import auth
from api.models import Token, UserInfo, Apps
from rest_framework.response import Response
from api.utils.serializer import UserInfoSerializer
from django.core.cache import cache
from rest_framework.views import APIView
import binascii
import os, datetime, json
from api.utils.utils import get_captcha, valid_captcha, is_valid_domain, is_valid_phone, \
get_sender_sms_token, is_valid_email, is_valid_sender_code, get_sender_email_token, get_random_username, \
check_username_exists
from api.utils.auth import ApiTokenAuthentication
from api.utils.response import BaseResponse
from fir_ser.settings import CACHE_KEY_TEMPLATE, SERVER_DOMAIN, REGISTER, LOGIN
from api.utils.storage.caches import login_auth_failed, set_default_app_wx_easy
import logging
from api.views.login import UserInfoView
logger = logging.getLogger(__name__)
class CliUserInfoView(UserInfoView):
authentication_classes = [ApiTokenAuthentication, ]

@ -0,0 +1,17 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# project: 3月
# author: liuyu
# date: 2020/3/6
from api.utils.auth import ApiTokenAuthentication
from api.views.uploads import AppAnalyseView, UploadView
class CliAppAnalyseView(AppAnalyseView):
authentication_classes = [ApiTokenAuthentication, ]
class CliUploadView(UploadView):
authentication_classes = [ApiTokenAuthentication, ]

@ -16,19 +16,8 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, re_path, include
from rest_framework.routers import DefaultRouter
# from api.views.course import CourseView,CourseDetailView,CourseCategoryView
from api.views.login import LoginView
from api.views.logout import LogoutView
# from api.views.shoppingcart import ShoppingCarView
# from api.views.account import AccountView
# from api.views.payment import PaymentView
# from api.views.payment import get_pay_url
# from api.views.order import OrderView
# from api.views.trade import AlipayTradeView
# router=DefaultRouter()
# router.register("courses", CourseView)
# router.register("coursedetail", CourseDetailView)
# router.register("course/category", CourseCategoryView)
from django.views.static import serve
from fir_ser import settings
from api.views.download import DownloadView, InstallView
@ -38,13 +27,8 @@ urlpatterns = [
re_path('fly.admin/', admin.site.urls),
# path("",include(router.urls)),
re_path("api/v1/fir/server/", include('api.urls')),
re_path("api/v2/fir/server/", include('cli.urls')),
re_path('^captcha/', include('captcha.urls')),
# re_path("shoppingcar/",ShoppingCarView.as_view()),
# re_path("account/",AccountView.as_view()),
# re_path("payment/",PaymentView.as_view()),
# re_path("myorder/",OrderView.as_view()),
# re_path("get_pay_url/",get_pay_url),s
# re_path("api/v1/trade/alipay/",AlipayTradeView),
# media路径配置
re_path('files/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
re_path("download/(?P<filename>\w+\.\w+)$", DownloadView.as_view(), name="download"),

Loading…
Cancel
Save