Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
douban-api-proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
douban-api-proxy
Commits
d3986ca1
Commit
d3986ca1
authored
Dec 11, 2020
by
Ozzieisaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Server side file browser
parent
2508c1ab
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
74 additions
and
94 deletions
+74
-94
admin.py
cps/admin.py
+22
-13
main.js
cps/static/js/main.js
+40
-70
config_edit.html
cps/templates/config_edit.html
+9
-9
modal_dialogs.html
cps/templates/modal_dialogs.html
+2
-1
web.py
cps/web.py
+1
-1
No files found.
cps/admin.py
View file @
d3986ca1
...
...
@@ -520,13 +520,21 @@ def list_restriction(res_type):
response
.
headers
[
"Content-Type"
]
=
"application/json; charset=utf-8"
return
response
@
admi
.
route
(
"/basicconfig/pathchooser/"
)
@
unconfigured
def
config_pathchooser
():
return
pathchooser
()
@
admi
.
route
(
"/ajax/pathchooser/"
,
endpoint
=
"pathchooser"
)
@
admi
.
route
(
"/ajax/filechooser/"
,
endpoint
=
"filechooser"
)
@
admi
.
route
(
"/ajax/pathchooser/"
)
@
login_required
@
admin_required
def
ajax_pathchooser
():
return
pathchooser
()
def
pathchooser
():
browse_for
=
"folder"
if
request
.
endpoint
==
"admin.pathchooser"
else
"file"
browse_for
=
"folder"
# if request.endpoint == "admin.pathchooser" else "file"
folder_only
=
request
.
args
.
get
(
'folder'
,
False
)
==
"true"
file_filter
=
request
.
args
.
get
(
'filter'
,
""
)
path
=
os
.
path
.
normpath
(
request
.
args
.
get
(
'path'
,
""
))
if
os
.
path
.
isfile
(
path
):
...
...
@@ -538,11 +546,11 @@ def pathchooser():
abs
=
False
if
os
.
path
.
isdir
(
path
):
if
os
.
path
.
isabs
(
path
):
cwd
=
os
.
path
.
realpath
(
path
)
abs
=
True
else
:
cwd
=
os
.
path
.
relpath
(
path
)
#
if os.path.isabs(path):
cwd
=
os
.
path
.
realpath
(
path
)
abs
=
True
#
else:
#
cwd = os.path.relpath(path)
else
:
cwd
=
os
.
getcwd
()
...
...
@@ -564,18 +572,19 @@ def pathchooser():
folders
=
[]
files
=
[]
locale
=
get_locale
()
#
locale = get_locale()
for
f
in
folders
:
try
:
data
=
{
"name"
:
f
,
"fullpath"
:
os
.
path
.
join
(
cwd
,
f
)}
data
[
"sort"
]
=
data
[
"fullpath"
]
.
lower
()
data
[
"modified"
]
=
format_datetime
(
datetime
.
fromtimestamp
(
int
(
os
.
path
.
getmtime
(
os
.
path
.
join
(
cwd
,
f
)))),
format
=
'short'
,
locale
=
locale
)
data
[
"ext"
]
=
os
.
path
.
splitext
(
f
)[
1
]
except
Exception
:
continue
if
os
.
path
.
isfile
(
os
.
path
.
join
(
cwd
,
f
)):
if
folder_only
:
continue
if
file_filter
!=
""
and
file_filter
!=
f
:
continue
data
[
"type"
]
=
"file"
data
[
"size"
]
=
os
.
path
.
getsize
(
os
.
path
.
join
(
cwd
,
f
))
...
...
@@ -604,7 +613,7 @@ def pathchooser():
return
json
.
dumps
(
context
)
@
admi
.
route
(
"/config"
,
methods
=
[
"GET"
,
"POST"
])
@
admi
.
route
(
"/
basic
config"
,
methods
=
[
"GET"
,
"POST"
])
@
unconfigured
def
basic_configuration
():
logout_user
()
...
...
cps/static/js/main.js
View file @
d3986ca1
...
...
@@ -213,22 +213,33 @@ $(function() {
});
}
function
fillFileTable
(
path
,
type
)
{
if
(
type
===
"dir"
)
{
var
request_path
=
"/../
../ajax
/pathchooser/"
;
function
fillFileTable
(
path
,
type
,
folder
,
filt
)
{
if
(
window
.
location
.
pathname
.
endsWith
(
"/basicconfig"
)
)
{
var
request_path
=
"/../
basicconfig
/pathchooser/"
;
}
else
{
var
request_path
=
"/../../ajax/
file
chooser/"
;
var
request_path
=
"/../../ajax/
path
chooser/"
;
}
$
.
ajax
({
dataType
:
"json"
,
data
:
{
path
:
path
,
folder
:
folder
,
filter
:
filt
},
url
:
window
.
location
.
pathname
+
request_path
,
success
:
function
success
(
data
)
{
if
(
$
(
"#element_selected"
).
text
()
===
""
)
{
$
(
"#element_selected"
).
text
(
data
.
cwd
);
}
$
(
"#file_table > tbody > tr"
).
each
(
function
()
{
if
(
$
(
this
).
attr
(
"id"
)
!==
"parent"
)
{
$
(
this
).
closest
(
"tr"
).
remove
();
}
else
{
if
(
data
.
absolute
&&
data
.
parentdir
!==
""
)
{
$
(
this
)[
0
].
attributes
[
'data-path'
].
value
=
data
.
parentdir
;
}
else
{
$
(
this
)[
0
].
attributes
[
'data-path'
].
value
=
".."
;
}
}
});
if
(
data
.
parentdir
!==
""
)
{
...
...
@@ -444,83 +455,42 @@ $(function() {
$
(
"#fileModal"
).
on
(
"show.bs.modal"
,
function
(
e
)
{
//get data-id attribute of the clicked element and store in button
//var submit = true;
//var cwd = "{{oldfile|default(cwd, True)|abspath|replace('\\', '\\\\')}}";
//var isabsolute = true;
fillFileTable
(
""
,
"dir"
);
var
target
=
$
(
e
.
relatedTarget
);
var
path
=
$
(
"#"
+
target
.
data
(
"link"
))[
0
].
value
;
var
folder
=
target
.
data
(
"folderonly"
);
var
filter
=
target
.
data
(
"filefilter"
);
$
(
"#element_selected"
).
text
(
path
);
$
(
"#file_confirm"
)[
0
].
attributes
[
"data-link"
].
value
=
target
.
data
(
"link"
);
$
(
"#file_confirm"
)[
0
].
attributes
[
"data-folderonly"
].
value
=
(
typeof
folder
===
'undefined'
)
?
false
:
true
;
$
(
"#file_confirm"
)[
0
].
attributes
[
"data-filefilter"
].
value
=
(
typeof
filter
===
'undefined'
)
?
""
:
filter
;
$
(
"#file_confirm"
)[
0
].
attributes
[
"data-newfile"
].
value
=
target
.
data
(
"newfile"
);
fillFileTable
(
path
,
"dir"
,
folder
,
filter
);
});
//(".tr-clickable").on("click",
$
(
document
).
on
(
"click"
,
".tr-clickable"
,
function
()
{
var
path
=
this
.
attributes
[
'data-path'
].
value
;
var
type
=
this
.
attributes
[
'data-type'
].
value
;
fillFileTable
(
path
,
type
);
$
(
"#file_confirm"
).
click
(
function
()
{
$
(
"#"
+
$
(
this
).
data
(
"link"
))[
0
].
value
=
$
(
"#element_selected"
).
text
()
});
/*{% if type == 'folder' %} {# browsing for folder #}
var abspath = "{{url_for('app.pathchooser') + '?path=' + cwd|abspath|quote_plus}}";
var relpath = "{{url_for('app.pathchooser') + '?path=' + cwd|relpath|quote_plus}}";
{% else %} {# browsing for file #}
var abspath = "{{url_for('app.filechooser') + '?path=' + oldfile|default(cwd, True)|abspath|quote_plus}}";
var relpath = "{{url_for('app.filechooser') + '?path=' + oldfile|default(cwd, True)|relpath|quote_plus}}";
{% endif %}*/
/*document.addEventListener("readystatechange", function(event) {
if (this.readyState === "complete") {
document.getElementById("tbody").style.height = (window.innerHeight - 25) + "px";
window.onresize = function (event) {
document.getElementById("tbody").style.height = (window.innerHeight - 25) + "px";
};
var clickables = document.getElementsByClassName("tr-clickable");
for (var i = 0; i < clickables.length; i++) {
clickables[i].onclick = (function () {
var onclick = clickables[i].onclick;
return function (e) {
if (onclick != null && !onclick()) {
return false
}
if (this.dataset.href !== undefined && this.dataset.href !== "#") {
window.location.href = this.dataset.href;
return false
} else {
return true;
}
}
})();
}
}
});
function updateParent()
{
if (window.top.SettingsUI !== undefined) {
window.top.SettingsUI.prototype.pathchooserChanged(this);
}
}
function setInvalid() {
submit = false;
cwd = "";
updateParent();
$
(
document
).
on
(
"click"
,
".tr-clickable"
,
function
()
{
var
path
=
this
.
attributes
[
"data-path"
].
value
;
var
type
=
this
.
attributes
[
"data-type"
].
value
;
var
folder
=
$
(
file_confirm
).
data
(
"folderonly"
);
var
filter
=
$
(
file_confirm
).
data
(
"filefilter"
);
var
newfile
=
$
(
file_confirm
).
data
(
"newfile"
);
if
(
newfile
!==
'undefined'
)
{
$
(
"#element_selected"
).
text
(
path
+
$
(
"#new_file"
.
text
()));
}
else
{
$
(
"#element_selected"
).
text
(
path
);
}
function setValid() {
submit = true;
updateParent();
if
(
type
===
"dir"
)
{
fillFileTable
(
path
,
type
,
folder
,
filter
);
}
function setFile(fullpath, name)
{
cwd = fullpath;
/*{*% if type == "file" %} {# browsing for file #}
abspath = "{{url_for('app.filechooser')}}?path={{cwd|abspath|quote_plus}}" + encodeURIComponent(name);
relpath = "{{url_for('app.filechooser')}}?path={{cwd|relpath|quote_plus}}" + encodeURIComponent(name);
{% endif %}*/
/*setValid();
}*/
});
$
(
"#btndeletetoken"
).
click
(
function
()
{
//get data-id attribute of the clicked element
var
pathname
=
document
.
getElementsByTagName
(
"script"
),
src
=
pathname
[
pathname
.
length
-
1
].
src
;
var
path
=
src
.
substring
(
0
,
src
.
lastIndexOf
(
"/"
));
// var domainId = $(this).value("domainId");
$
.
ajax
({
method
:
"get"
,
url
:
path
+
"/../../kobo_auth/deleteauthtoken/"
+
this
.
value
,
...
...
cps/templates/config_edit.html
View file @
d3986ca1
...
...
@@ -19,7 +19,7 @@
<div
class=
"form-group required input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_calibre_dir"
name=
"config_calibre_dir"
value=
"{% if config.config_calibre_dir != None %}{{ config.config_calibre_dir }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"library_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
data-toggle=
"modal"
id=
"converter_modal_path"
data-link=
"config_calibre_dir"
data-filefilter=
"metadata.db"
data-target=
"#fileModal"
id=
"library_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
{% if feature_support['gdrive'] %}
...
...
@@ -94,14 +94,14 @@
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_certfile"
name=
"config_certfile"
value=
"{% if config.config_certfile != None %}{{ config.config_certfile }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"certfile_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
data-toggle=
"modal"
data-link=
"config_certfile"
data-target=
"#fileModal"
id=
"certfile_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
<label
for=
"config_calibre_dir"
>
{{_('SSL Keyfile location (leave it empty for non-SSL Servers)')}}
</label>
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_keyfile"
name=
"config_keyfile"
value=
"{% if config.config_keyfile != None %}{{ config.config_keyfile }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"keyfile_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"keyfile_path"
data-toggle=
"modal"
data-link=
"config_keyfile"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
<div
class=
"form-group"
>
...
...
@@ -268,21 +268,21 @@
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_ldap_cacert_path"
name=
"config_ldap_cacert_path"
value=
"{% if config.config_ldap_cacert_path != None %}{{ config.config_ldap_cacert_path }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"library_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"library_path"
data-toggle=
"modal"
data-link=
"config_ldap_cacert_path"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
<label
for=
"config_ldap_cert_path"
>
{{_('LDAP Certificate Path (Only needed for Client Certificate Authentication)')}}
</label>
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_ldap_cert_path"
name=
"config_ldap_cert_path"
value=
"{% if config.config_ldap_cert_path != None %}{{ config.config_ldap_cert_path }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"library_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"library_path"
data-toggle=
"modal"
data-link=
"config_ldap_cert_path"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
<label
for=
"config_ldap_key_path"
>
{{_('LDAP Keyfile Path (Only needed for Client Certificate Authentication)')}}
</label>
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_ldap_key_path"
name=
"config_ldap_key_path"
value=
"{% if config.config_ldap_key_path != None %}{{ config.config_ldap_key_path }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"library_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"library_path"
data-toggle=
"modal"
data-link=
"config_ldap_key_path"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
</div>
...
...
@@ -384,7 +384,7 @@
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_converterpath"
name=
"config_converterpath"
value=
"{% if config.config_converterpath != None %}{{ config.config_converterpath }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"converter_modal_path"
data-toggle=
"modal
"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
data-toggle=
"modal"
id=
"converter_modal_path"
data-link=
"config_converterpath
"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
<div
class=
"form-group"
>
...
...
@@ -395,7 +395,7 @@
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_kepubifypath"
name=
"config_kepubifypath"
value=
"{% if config.config_kepubifypath != None %}{{ config.config_kepubifypath }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"kepubify_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"kepubify_path"
data-toggle=
"modal"
data-link=
"config_kepubifypath"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
{% if feature_support['rar'] %}
...
...
@@ -403,7 +403,7 @@
<div
class=
"form-group input-group"
>
<input
type=
"text"
class=
"form-control"
id=
"config_rarfile_location"
name=
"config_rarfile_location"
value=
"{% if config.config_rarfile_location != None %}{{ config.config_rarfile_location }}{% endif %}"
autocomplete=
"off"
>
<span
class=
"input-group-btn"
>
<button
type=
"button"
id=
"unrar_path"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
<button
type=
"button"
id=
"unrar_path"
data-toggle=
"modal"
data-link=
"config_rarfile_location"
data-target=
"#fileModal"
class=
"btn btn-default"
><span
class=
"glyphicon glyphicon-folder-open"
></span></button>
</span>
</div>
{% endif %}
...
...
cps/templates/modal_dialogs.html
View file @
d3986ca1
...
...
@@ -94,7 +94,8 @@
</table>
</div>
<div
class=
"modal-footer"
>
<input
type=
"button"
class=
"btn btn-primary"
value=
"{{_('Select')}}"
name=
"file_confirm"
id=
"file_confirm"
data-dismiss=
"modal"
>
<div
class=
"text-left"
id=
"element_selected"
></div>
<input
type=
"button"
class=
"btn btn-primary"
data-path=
""
data-link=
""
data-folderonly=
""
data-filefilter=
""
data-newfile=
""
value=
"{{_('Select')}}"
name=
"file_confirm"
id=
"file_confirm"
data-dismiss=
"modal"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
{{_('Cancel')}}
</button>
</div>
</div>
...
...
cps/web.py
View file @
d3986ca1
...
...
@@ -304,7 +304,7 @@ def before_request():
g
.
shelves_access
=
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
or_
(
ub
.
Shelf
.
is_public
==
1
,
ub
.
Shelf
.
user_id
==
current_user
.
id
))
.
order_by
(
ub
.
Shelf
.
name
)
.
all
()
if
not
config
.
db_configured
and
request
.
endpoint
not
in
(
'admin.basic_configuration'
,
'login'
)
and
'/static/'
not
in
request
.
path
:
'admin.basic_configuration'
,
'login'
,
"admin.config_pathchooser"
)
and
'/static/'
not
in
request
.
path
:
return
redirect
(
url_for
(
'admin.basic_configuration'
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment