mirror of https://github.com/IoTcat/PyOne.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
18 KiB
464 lines
18 KiB
#-*- coding=utf-8 -*- |
|
from flask import Blueprint,redirect,url_for,request,render_template,flash,session,jsonify,Response,make_response |
|
from flask_sqlalchemy import Pagination |
|
from function import * |
|
from config import * |
|
from run import FetchData,path_list,GetName,CodeType,_remote_content,rd,has_item,AddResource |
|
import os |
|
import io |
|
import re |
|
import subprocess |
|
import random |
|
import urllib |
|
from shelljob import proc |
|
import eventlet |
|
|
|
eventlet.monkey_patch() |
|
|
|
|
|
admin = Blueprint('admin', __name__,url_prefix='/admin') |
|
|
|
############功能函数 |
|
def set(key,value,user='A'): |
|
allow_key=['title','downloadUrl_timeout','allow_site','password','client_secret','client_id','share_path','other_name','tj_code'] |
|
if key not in allow_key: |
|
return u'禁止修改' |
|
print 'set {}:{}'.format(key,value) |
|
config_path=os.path.join(config_dir,'config.py') |
|
with open(config_path,'r') as f: |
|
old_text=f.read() |
|
with open(config_path,'w') as f: |
|
if key in ['client_secret','client_id','share_path','other_name']: |
|
old_kv=re.findall('"{}":{{[\w\W]*?}}'.format(user),old_text)[0] |
|
new_kv=re.sub('"{}":.*?,'.format(key),'"{}":"{}",'.format(key,value),old_kv) |
|
new_text=old_text.replace(old_kv,new_kv) |
|
elif key=='allow_site': |
|
value=value.split(',') |
|
new_text=re.sub('{}=.*'.format(key),'{}={}'.format(key,value),old_text) |
|
elif key=='tj_code': |
|
new_text=re.sub('{}=.*'.format(key),'{}="""{}"""'.format(key,value),old_text) |
|
else: |
|
new_text=re.sub('{}=.*'.format(key),'{}="{}"'.format(key,value),old_text) |
|
f.write(new_text) |
|
|
|
|
|
############视图函数 |
|
@admin.before_request |
|
def before_request(): |
|
if request.endpoint.startswith('admin') and request.endpoint!='admin.login' and session.get('login') is None: #and request.endpoint!='admin.install' |
|
return redirect(url_for('admin.login')) |
|
|
|
|
|
########web console |
|
@admin.route('/web_console') |
|
def web_console(): |
|
g = proc.Group() |
|
action=request.args.get('action') |
|
allow_action=['UpdateFile','UploadDir','Upload'] |
|
if action not in allow_action: |
|
return make_response('error') |
|
if action in ['UploadDir','Upload']: |
|
local=urllib.unquote(request.args.get('local')) |
|
remote=urllib.unquote(request.args.get('remote')) |
|
user=urllib.unquote(request.args.get('user')) |
|
cmd=["python","-u",os.path.join(config_dir,'function.py'),action,local,remote,user] |
|
elif action=='UpdateFile': |
|
type_=request.args.get('type') |
|
cmd=["python","-u",os.path.join(config_dir,'function.py'),'UpdateFile',type_] |
|
else: |
|
cmd=["python","-u",os.path.join(config_dir,'function.py'),action] |
|
p = g.run(cmd) |
|
def read_process(): |
|
while g.is_pending(): |
|
lines = g.readlines() |
|
for proc, line in lines: |
|
yield "data:" + line + "\n\n" |
|
yield "data:end\n\n" |
|
return Response(read_process(), mimetype= 'text/event-stream') |
|
|
|
########admin |
|
@admin.route('/',methods=['GET','POST']) |
|
@admin.route('/setting',methods=['GET','POST']) |
|
def setting(): |
|
if request.method=='POST': |
|
title=request.form.get('title','PyOne') |
|
downloadUrl_timeout=request.form.get('downloadUrl_timeout',5*60) |
|
allow_site=request.form.get('allow_site','no-referrer') |
|
tj_code=request.form.get('tj_code','') |
|
password1=request.form.get('password1') |
|
password2=request.form.get('password2') |
|
new_password=password |
|
if ((password1 is not None and password2 is None) or (password1 is None and password2 is not None)): |
|
flash(u'请输入新密码或者二次确认新密码') |
|
elif password1 is not None and password2 is not None and password1!=password2: |
|
flash(u'两次输入密码不相同') |
|
elif password1 is not None and password2 is not None and password1==password2 and password1!='': |
|
new_password=password1 |
|
set('title',title) |
|
set('downloadUrl_timeout',downloadUrl_timeout) |
|
set('allow_site',allow_site) |
|
set('tj_code',tj_code) |
|
set('password',new_password) |
|
####网盘信息处理 |
|
for k,v in request.form.to_dict().items(): |
|
if 'share_path' in k or 'other_name' in k: |
|
user=re.findall('\[(.*?)\]',k)[0] |
|
key=re.findall('(.*)\[',k)[0] |
|
print('setting {}\'s {}\'s value {}'.format(user,key,v)) |
|
set(key,v,user) |
|
reload() |
|
return render_template('admin/setting.html') |
|
return render_template('admin/setting.html') |
|
|
|
|
|
|
|
|
|
@admin.route('/upload',methods=["POST","GET"]) |
|
def upload(): |
|
if request.method=='POST': |
|
user=request.form.get('user').encode('utf-8') |
|
local=request.form.get('local').encode('utf-8') |
|
remote=request.form.get('remote').encode('utf-8') |
|
if not os.path.exists(local): |
|
flash('本地目录/文件不存在') |
|
return redirect(url_for('admin.upload')) |
|
if os.path.isfile(local): |
|
action='Upload' |
|
else: |
|
action='UploadDir' |
|
return render_template('admin/upload.html',remote=remote,local=local,action=action,user=user) |
|
return render_template('admin/upload.html') |
|
|
|
|
|
|
|
@admin.route('/cache',methods=["POST","GET"]) |
|
def cache(): |
|
if request.method=='POST': |
|
type=request.form.get('type') |
|
return render_template('admin/cache.html',type=type,action='UpdateFile') |
|
return render_template('admin/cache.html') |
|
|
|
|
|
@admin.route('/manage',methods=["POST","GET"]) |
|
def manage(): |
|
if request.method=='POST': |
|
pass |
|
path=urllib.unquote(request.args.get('path','A:/')) |
|
user,n_path=path.split(':') |
|
if n_path=='': |
|
path=':'.join([user,'/']) |
|
page=request.args.get('page',1,type=int) |
|
image_mode=request.args.get('image_mode') |
|
sortby=request.args.get('sortby') |
|
order=request.args.get('order') |
|
if sortby: |
|
sortby=request.args.get('sortby') |
|
else: |
|
sortby=request.cookies.get('admin_sortby') if request.cookies.get('admin_sortby') is not None else 'lastModtime' |
|
sortby=sortby |
|
if order: |
|
order=request.args.get('order') |
|
else: |
|
order=request.cookies.get('admin_order') if request.cookies.get('admin_order') is not None else 'desc' |
|
order=order |
|
resp,total = FetchData(path=path,page=page,per_page=50,sortby=sortby,order=order) |
|
pagination=Pagination(query=None,page=page, per_page=50, total=total, items=None) |
|
if path.split(':',1)[-1]=='/': |
|
path=':'.join([path.split(':',1)[0],'']) |
|
resp=make_response(render_template('admin/manage.html',pagination=pagination,items=resp,path=path,sortby=sortby,order=order,cur_user=user,endpoint='admin.manage')) |
|
resp.set_cookie('admin_sortby',str(sortby)) |
|
resp.set_cookie('admin_order',str(order)) |
|
return resp |
|
|
|
|
|
@admin.route('/edit',methods=["GET","POST"]) |
|
def edit(): |
|
if request.method=='POST': |
|
fileid=request.form.get('fileid') |
|
user=request.form.get('user') |
|
content=request.form.get('content').encode('utf-8') |
|
info={} |
|
token=GetToken(user=user) |
|
app_url=GetAppUrl() |
|
headers={'Authorization':'bearer {}'.format(token)} |
|
url=app_url+'v1.0/me/drive/items/{}/content'.format(fileid) |
|
try: |
|
r=requests.put(url,headers=headers,data=content,timeout=10) |
|
data=json.loads(r.content) |
|
if data.get('id'): |
|
info['status']=0 |
|
info['msg']='修改成功' |
|
rd.delete('{}:content'.format(fileid)) |
|
file=items.find_one({'id':fileid}) |
|
name=file['name'] |
|
path=file['path'].replace('/'+name,'').replace(name,'') |
|
if path=='': |
|
path='/' |
|
if not path.startswith('/'): |
|
path='/'+path |
|
path='{}:{}'.format(user,path) |
|
key='has_item$#$#$#$#{}$#$#$#$#{}'.format(path,name) |
|
rd.delete(key) |
|
else: |
|
info['status']=0 |
|
info['msg']=data.get('error').get('message') |
|
except Exception as e: |
|
print e |
|
info['status']=0 |
|
info['msg']='修改超时' |
|
return jsonify(info) |
|
fileid=request.args.get('fileid') |
|
user=request.args.get('user') |
|
name=GetName(fileid) |
|
ext=name.split('.')[-1] |
|
language=CodeType(ext) |
|
if language is None: |
|
language='Text' |
|
content=_remote_content(fileid,user) |
|
return render_template('admin/edit.html',content=content,fileid=fileid,name=name,language=language,cur_user=user) |
|
|
|
###本地上传文件只onedrive,通过服务器中转 |
|
@admin.route('/upload_local',methods=['POST','GET']) |
|
def upload_local(): |
|
user,remote_folder=request.args.get('path').split(':') |
|
return render_template('admin/upload_local.html',remote_folder=remote_folder,cur_user=user) |
|
|
|
@admin.route('/checkChunk', methods=['POST']) |
|
def checkChunk(): |
|
md5=request.form.get('fileMd5') |
|
fileName=request.form.get('name').encode('utf-8') |
|
chunk=request.form.get('chunk',0,type=int) |
|
filename = u'./upload/{}-{}'.format(fileName, chunk) |
|
if os.path.exists(filename): |
|
exists=True |
|
else: |
|
exists=False |
|
return jsonify({'ifExist':exists}) |
|
|
|
|
|
@admin.route('/mergeChunks', methods=['POST']) |
|
def mergeChunks(): |
|
fileName=request.form.get('fileName').encode('utf-8') |
|
md5=request.form.get('fileMd5') |
|
chunk = 0 # 分片序号 |
|
with open(u'./upload/{}'.format(fileName), 'wb') as target_file: # 创建新文件 |
|
while True: |
|
try: |
|
filename = u'./upload/{}-{}'.format(fileName, chunk) |
|
source_file = open(filename, 'rb') # 按序打开每个分片 |
|
target_file.write(source_file.read()) # 读取分片内容写入新文件 |
|
source_file.close() |
|
except IOError as msg: |
|
break |
|
chunk += 1 |
|
os.remove(filename) # 删除该分片,节约空间 |
|
return jsonify({'upload':True}) |
|
|
|
|
|
@admin.route('/recv_upload', methods=['POST']) |
|
def recv_upload(): # 接收前端上传的一个分片 |
|
md5=request.form.get('fileMd5') |
|
name=request.form.get('name').encode('utf-8') |
|
chunk_id=request.form.get('chunk',0,type=int) |
|
filename = '{}-{}'.format(name,chunk_id) |
|
upload_file = request.files['file'] |
|
upload_file.save(u'./upload/{}'.format(filename)) |
|
return jsonify({'upload_part':True}) |
|
|
|
|
|
@admin.route('/to_one',methods=['GET']) |
|
def server_to_one(): |
|
user=request.args.get('user') |
|
filename=request.args.get('filename').encode('utf-8') |
|
remote_folder=request.args.get('remote_folder').encode('utf-8') |
|
if remote_folder!='/': |
|
remote_folder=remote_folder+'/' |
|
local_dir=os.path.join(config_dir,'upload') |
|
filepath=urllib.unquote(os.path.join(local_dir,filename)) |
|
_upload_session=Upload_for_server(filepath,remote_folder,user) |
|
def read_status(): |
|
while 1: |
|
try: |
|
msg=_upload_session.next()['status'] |
|
yield "data:" + msg + "\n\n" |
|
except Exception as e: |
|
msg='end' |
|
yield "data:" + msg + "\n\n" |
|
os.remove(filepath) |
|
break |
|
return Response(read_status(), mimetype= 'text/event-stream') |
|
|
|
|
|
|
|
###本地上传文件只onedrive,通过服务器中转 |
|
@admin.route('/setFile',methods=["GET","POST"]) |
|
@admin.route('/setFile/<filename>',methods=["GET","POST"]) |
|
def setFile(filename=None): |
|
if request.method=='POST': |
|
path=request.form.get('path') |
|
user,n_path=path.split(':') |
|
filename=request.form.get('filename') |
|
if not n_path.startswith('/'): |
|
n_path='/'+n_path |
|
remote_file=os.path.join(n_path,filename) |
|
content=request.form.get('content').encode('utf-8') |
|
info={} |
|
token=GetToken(user=user) |
|
app_url=GetAppUrl() |
|
headers={'Authorization':'bearer {}'.format(token)} |
|
url=app_url+'v1.0/me/drive/items/root:{}:/content'.format(remote_file) |
|
try: |
|
r=requests.put(url,headers=headers,data=content,timeout=10) |
|
data=json.loads(r.content) |
|
if data.get('id'): |
|
AddResource(data,user) |
|
info['status']=0 |
|
info['msg']='添加成功' |
|
key='has_item$#$#$#$#{}$#$#$#$#{}'.format(path,filename) |
|
rd.delete(key) |
|
else: |
|
info['status']=0 |
|
info['msg']=data.get('error').get('message') |
|
except Exception as e: |
|
info['status']=0 |
|
info['msg']='超时' |
|
return jsonify(info) |
|
path=urllib.unquote(request.args.get('path')) |
|
user,n_path=path.split(':') |
|
_,fid,i=has_item(path,filename) |
|
if fid!=False: |
|
return redirect(url_for('admin.edit',fileid=fid,user=user)) |
|
return render_template('admin/setpass.html',path=path,filename=filename,cur_user=user) |
|
|
|
|
|
@admin.route('/delete',methods=["POST"]) |
|
def delete(): |
|
ids=request.form.get('id') |
|
user=request.form.get('user') |
|
if ids is None: |
|
return jsonify({'msg':u'请选择要删除的文件','status':0}) |
|
ids=ids.split('##') |
|
infos={} |
|
infos['status']=1 |
|
infos['delete']=0 |
|
infos['fail']=0 |
|
for id in ids: |
|
file=items.find_one({'id':id}) |
|
name=file['name'] |
|
# path=file['path'].replace('/'+name,'').replace(name,'') |
|
if file['parent']=='': |
|
path='/' |
|
else: |
|
path=items.find_one({'id':file['parent']})['path'] |
|
if not path.startswith('/'): |
|
path='/'+path |
|
path='{}:{}'.format(user,path) |
|
key='has_item$#$#$#$#{}$#$#$#$#{}'.format(path,name) |
|
rd.delete(key) |
|
kc='{}:content'.format(id) |
|
rd.delete(kc) |
|
status=DeleteRemoteFile(id,user) |
|
if status: |
|
infos['delete']+=1 |
|
else: |
|
infos['fail']+=1 |
|
return jsonify(infos) |
|
|
|
|
|
@admin.route('/add_folder',methods=['POST']) |
|
def AddFolder(): |
|
folder_name=request.form.get('folder_name') |
|
path=request.args.get('path') |
|
user,grand_path=path.split(':') |
|
if grand_path=='' or grand_path is None: |
|
grand_path='/' |
|
else: |
|
if grand_path.startswith('/'): |
|
grand_path=grand_path[1:] |
|
result=CreateFolder(folder_name,grand_path,user) |
|
return jsonify({'result':result}) |
|
|
|
@admin.route('/move_file',methods=['POST']) |
|
def MoveFileToNewFolder(): |
|
fileid=request.form.get('fileid') |
|
user=request.form.get('user') |
|
new_folder_path=request.form.get('new_folder_path') |
|
if new_folder_path=='' or new_folder_path is None: |
|
new_folder_path='/' |
|
else: |
|
if new_folder_path.startswith('/'): |
|
new_folder_path=new_folder_path[1:] |
|
result=MoveFile(fileid,new_folder_path,user) |
|
return jsonify({'result':result}) |
|
|
|
|
|
|
|
|
|
|
|
@admin.route('/login',methods=["POST","GET"]) |
|
def login(): |
|
if request.method=='POST': |
|
password1=request.form.get('password') |
|
if password1==password: |
|
session['login']='true' |
|
return redirect(url_for('admin.setting')) |
|
else: |
|
return render_template('admin/login.html') |
|
return render_template('admin/login.html') |
|
|
|
|
|
@admin.route('/logout',methods=['GET','POST']) |
|
def logout(): |
|
session.pop('login',None) |
|
return redirect('/') |
|
|
|
@admin.route('/reload',methods=['GET','POST']) |
|
def reload(): |
|
cmd='supervisorctl -c {} restart pyone'.format(os.path.join(config_dir,'supervisord.conf')) |
|
subprocess.Popen(cmd,shell=True) |
|
flash('正在重启网站...如果更改了分享目录,请更新缓存') |
|
return redirect(url_for('admin.setting')) |
|
|
|
|
|
|
|
|
|
###########################################安装 |
|
@admin.route('/install',methods=['POST','GET']) |
|
def install(): |
|
if request.method=='POST': |
|
step=request.form.get('step',type=int) |
|
user=request.form.get('user') |
|
if step==1: |
|
client_secret=request.form.get('client_secret') |
|
client_id=request.form.get('client_id') |
|
redirect_uri='https://auth.3pp.me' |
|
set('client_secret',client_secret,user) |
|
set('client_id',client_id,user) |
|
login_url=LoginUrl.format(client_id=client_id,redirect_uri=redirect_uri) |
|
return render_template('admin/install_1.html',client_secret=client_secret,client_id=client_id,login_url=login_url,cur_user=user) |
|
else: |
|
client_secret=request.form.get('client_secret') |
|
client_id=request.form.get('client_id') |
|
code=request.form.get('code') |
|
redirect_uri='https://auth.3pp.me' |
|
#授权 |
|
headers['Content-Type']='application/x-www-form-urlencoded' |
|
data=AuthData.format(client_id=client_id,redirect_uri=urllib.quote(redirect_uri),client_secret=client_secret,code=code) |
|
url=OAuthUrl |
|
r=requests.post(url,data=data,headers=headers) |
|
Atoken=json.loads(r.text) |
|
if Atoken.get('access_token'): |
|
with open(os.path.join(config_dir,'data/{}_Atoken.json'.format(user)),'w') as f: |
|
json.dump(Atoken,f,ensure_ascii=False) |
|
refresh_token=Atoken.get('refresh_token') |
|
token=ReFreshToken(refresh_token,user) |
|
with open(os.path.join(config_dir,'data/{}_token.json'.format(user)),'w') as f: |
|
json.dump(token,f,ensure_ascii=False) |
|
return make_response('<h1>授权成功!<a href="/">点击进入首页</a><br>请在后台另开一个ssh窗口,运行:<pre>python function.py UpdateFile</pre>进行更新数据操作</h1>') |
|
else: |
|
return jsonify(Atoken) |
|
step=request.args.get('step',type=int) |
|
user=request.args.get('user','A') |
|
resp=render_template('admin/install_0.html',step=step,cur_user=user) |
|
return resp |
|
|
|
|