Skip to content

Commit

Permalink
Update dashboard function
Browse files Browse the repository at this point in the history
  • Loading branch information
cf-pages committed Jan 17, 2023
1 parent 5647c75 commit b287a26
Show file tree
Hide file tree
Showing 11 changed files with 625 additions and 13 deletions.
280 changes: 280 additions & 0 deletions admin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/lib/theme-chalk/index.css" integrity="sha256-ghr1zmXTODLKl1HULQd6fq1MIe7m3FJiNTOCT8sddLM=" crossorigin="anonymous">
</head>
<body>
<div id="app">
<el-container>
<el-header>
<div style="
margin: auto;
line-height: 60px;
font-size: xx-large;
position: relative;
">Dashboard


<span style="
position: absolute;
right: 0px;
" v-if="showLogoutButton"><el-button
size="mini"
type="info"
@click="handleLogout()">退出登录</el-button></span></div>
</el-header>
<el-main><el-row :gutter="12">
<el-col :span="24">
<el-card shadow="always">
记录总数量:
{{ Number }}
</el-card>
</el-col>
<!--<el-col :span="8">
<el-card shadow="hover">
<el-tooltip class="item" effect="dark" content="白名单数量" placement="top-start">
</el-tooltip>
白名单数量:{{ WhiteList }}
</el-card>
</el-col>
<el-col :span="8">
<el-card shadow="hover">
<el-tooltip class="item" effect="dark" content="黑名单数量" placement="top-start">
</el-tooltip>
黑名单数量:{{ BlackList }}
</el-card>
</el-col>-->
</el-row>
<template>
<el-table
:data="tableData.filter(data => !search || data.name.toLowerCase().includes(search.toLowerCase()))"
style="width: 100%">
<el-table-column
label="name"
prop="name">
</el-table-column>
<el-table-column
label="preview"
prop="preview">
<template slot-scope="scope">
<el-image
style="width: 100%; height: 100%;"
:src="'/file/'+scope.row.name"
:zoom-rate="1.2"
:preview-src-list="['/file/'+scope.row.name]"
fit="cover"
lazy
/>

</template>
</el-table-column>
<el-table-column
label="data"
prop="data">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>{{ scope.row.metadata }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.metadata }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column
align="right">
<template slot="header" slot-scope="scope">
<el-input
v-model="search"
size="mini"
placeholder="输入关键字搜索"/>
</template>
<template slot-scope="scope">
<el-button
size="mini"
type="primary"
@click="handleWhite(scope.$index,scope.row.name)">白名单</el-button>
<el-button
size="mini"
type="info"
@click="handleBlock(scope.$index,scope.row.name)">黑名单</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index,scope.row.name)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
</el-main>
</el-container>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" integrity="sha256-kXTEJcRFN330VirZFl6gj9+UM6gIKW195fYZeR3xDhc=" crossorigin="anonymous"></script>
<!-- import JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/index.js" integrity="sha256-OFVFYfqhQ9nDnKh+NfIsefpy/fnjTwkK909ZYgo45nw=" crossorigin="anonymous"></script>
<script>
var app=new Vue({
el: '#app',
data: {
Number:0,
WhiteList:0,
BlackList:0,
showLogoutButton:false,
tableData: [],
dialogFormVisible: false,
formLabelWidth: '120px',
form: {
name: '',
id: ''
},
search: '',
password:'123456'
},
methods: {
handleBlock(index,key) {
console.log(key);
if (confirm("确认加入黑名单吗?")) {
console.log("Yes")
var requestOptions = {
method: 'GET',
redirect: 'follow',
//include authorization credientials
credentials: 'include'
};

fetch("./api/manage/block/"+key, requestOptions)
.then(response => response.text())
.then(result => {console.log(result);
this.tableData[index].metadata=result;})
.catch(error => {alert("An error occurred while synchronizing data with the server, please check the network connection");console.log('error', error)});

} else {
console.log("No")
}
},
handleDelete(index,key) {
console.log(key);
if (confirm("确认删除该条记录吗?")) {
console.log("Yes")
var requestOptions = {
method: 'GET',
redirect: 'follow',
//include authorization credientials
credentials: 'include'
};

fetch("./api/manage/delete/"+key, requestOptions)
.then(response => response.text())
.then(result => {console.log(result);this.tableData.remove(index);})
.catch(error => {alert("An error occurred while synchronizing data with the server, please check the network connection");console.log('error', error)});

} else {
console.log("No")
}
},
handleWhite(index,key) {
console.log(key);
if (confirm("确认加入白名单吗?")) {
console.log("Yes")
var requestOptions = {
method: 'GET',
redirect: 'follow',
//include authorization credientials
credentials: 'include'
};
fetch("./api/manage/white/"+key, requestOptions)
.then(response => response.text())
.then(result => {console.log(result);this.tableData[index].metadata=result;})
.catch(error => {alert("An error occurred while synchronizing data with the server, please check the network connection");console.log('error', error)});

} else {
console.log("No")
}

},
handleLogout(){
window.location.href="./api/manage/logout";
}
},

mounted () {
//check if the user is logged in
//read the basic auth credientials from the browser
var requestOptions = {
method: 'GET',
redirect: 'follow',
//include authorization credientials
credentials: 'include'
};
fetch("./api/manage/check", requestOptions)
.then(response => response.text())
.then(result => {console.log(result);
if(result=="true"){
this.showLogoutButton=true;
}else if(result=="Not using basic auth."){

}
else{
window.location.href="./api/manage/login";
}
})
.catch(error => {alert("An error occurred while synchronizing data with the server, please check the network connection");console.log('error', error)});



Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var requestOptions = {
method: 'GET',
redirect: 'follow',
//include authorization credientials
credentials: 'include'

};


fetch("./api/manage/list", requestOptions)
//判断是否需要登录
.then(response => {
if(response.status==401){
alert("请先登录");
window.location.href="./api/manage/login";
}
else{
return response;
}
})
.then(response => response.text())
.then(result => {this.tableData=JSON.parse(result);console.log(result);this.Number=this.tableData.length})
.catch(error => {alert("An error occurred while synchronizing data with the server, please check the network connection");console.log('error', error)});

}
})

</script><!-- Hotjar Tracking Code -->
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:2531461,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script>
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "7t5ai7agat");
</script>
</html>
106 changes: 106 additions & 0 deletions functions/api/manage/_middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
async function errorHandling(context) {
try {
return await context.next();
} catch (err) {
return new Response(`${err.message}\n${err.stack}`, { status: 500 });
}
}

function basicAuthentication(request) {
const Authorization = request.headers.get('Authorization');

const [scheme, encoded] = Authorization.split(' ');

// The Authorization header must start with Basic, followed by a space.
if (!encoded || scheme !== 'Basic') {
throw new BadRequestException('Malformed authorization header.');
}

// Decodes the base64 value and performs unicode normalization.
// @see https://datatracker.ietf.org/doc/html/rfc7613#section-3.3.2 (and #section-4.2.2)
// @see https://dev.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
const buffer = Uint8Array.from(atob(encoded), character => character.charCodeAt(0));
const decoded = new TextDecoder().decode(buffer).normalize();

// The username & password are split by the first colon.
//=> example: "username:password"
const index = decoded.indexOf(':');

// The user & password are split by the first colon and MUST NOT contain control characters.
// @see https://tools.ietf.org/html/rfc5234#appendix-B.1 (=> "CTL = %x00-1F / %x7F")
if (index === -1 || /[\0-\x1F\x7F]/.test(decoded)) {
throw new BadRequestException('Invalid authorization value.');
}

return {
user: decoded.substring(0, index),
pass: decoded.substring(index + 1),
};
}

function UnauthorizedException(reason) {
return new Response(reason, {
status: 401,
statusText: 'Unauthorized',
headers: {
'Content-Type': 'text/plain;charset=UTF-8',
// Disables caching by default.
'Cache-Control': 'no-store',
// Returns the "Content-Length" header for HTTP HEAD requests.
'Content-Length': reason.length,
},
});
}

function BadRequestException(reason) {
return new Response(reason, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain;charset=UTF-8',
// Disables caching by default.
'Cache-Control': 'no-store',
// Returns the "Content-Length" header for HTTP HEAD requests.
'Content-Length': reason.length,
},
});
}


function authentication(context) {
//context.env.BASIC_USER="admin"
//context.env.BASIC_PASS="admin"
//check if the env variables Disable_Dashboard are set
if (context.env.DISABLE_DASHBOARD == "true") {
return new Response('Dashboard is disabled. Please enable to use this feature.', { status: 200 });
}

console.log(context.env.BASIC_USER)
if(typeof context.env.BASIC_USER == "undefined" || context.env.BASIC_USER == null || context.env.BASIC_USER == ""){
return context.next();
}else{
if (context.request.headers.has('Authorization')) {
// Throws exception when authorization fails.
const { user, pass } = basicAuthentication(context.request);


if (context.env.BASIC_USER !== user || context.env.BASIC_PASS !== pass) {
return UnauthorizedException('Invalid credentials.');
}else{
return context.next();
}

} else {
return new Response('You need to login.', {
status: 401,
headers: {
// Prompts the user for credentials.
'WWW-Authenticate': 'Basic realm="my scope", charset="UTF-8"',
},
});
}
}

}

export const onRequest = [errorHandling, authentication];
Loading

0 comments on commit b287a26

Please sign in to comment.