mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
The sharing function is almost done
This commit is contained in:
parent
4484668750
commit
958bc864c9
@ -77,7 +77,12 @@ class CustomJsonEncoder(DefaultJSONProvider):
|
||||
super().__init__(app)
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, WireguardConfiguration) or isinstance(o, Peer) or isinstance(o, PeerJob) or isinstance(o, Log) or isinstance(o, DashboardAPIKey):
|
||||
if (isinstance(o, WireguardConfiguration)
|
||||
or isinstance(o, Peer)
|
||||
or isinstance(o, PeerJob)
|
||||
or isinstance(o, Log)
|
||||
or isinstance(o, DashboardAPIKey)
|
||||
or isinstance(o, PeerShareLink)):
|
||||
return o.toJson()
|
||||
return super().default(self, o)
|
||||
|
||||
@ -335,19 +340,19 @@ class PeerJobs:
|
||||
return x < y
|
||||
|
||||
class PeerShareLink:
|
||||
def __init__(self, ShareID:str, Peer: str, Configuration: str, SharedDate: datetime, ExpireDate: datetime):
|
||||
def __init__(self, ShareID:str, Configuration: str, Peer: str, ExpireDate: datetime, ShareDate: datetime):
|
||||
self.ShareID = ShareID
|
||||
self.Peer = Peer
|
||||
self.Configuration = Configuration
|
||||
self.SharedDate = SharedDate
|
||||
self.ExpireData = ExpireDate
|
||||
self.ShareDate = ShareDate
|
||||
self.ExpireDate = ExpireDate
|
||||
|
||||
def toJson(self):
|
||||
return {
|
||||
"SharedID": self.ShareID,
|
||||
"ShareID": self.ShareID,
|
||||
"Peer": self.Peer,
|
||||
"Configuration": self.Configuration,
|
||||
"ShareDate": self.SharedDate
|
||||
"ExpireDate": self.ExpireDate
|
||||
}
|
||||
|
||||
class PeerShareLinks:
|
||||
@ -363,38 +368,50 @@ class PeerShareLinks:
|
||||
ExpireDate DATETIME,
|
||||
SharedDate DATETIME DEFAULT (datetime('now', 'localtime'))
|
||||
)
|
||||
""" % self.Name
|
||||
"""
|
||||
)
|
||||
sqldb.commit()
|
||||
|
||||
self.__getSharedLinks()
|
||||
# print(self.Links)
|
||||
def __getSharedLinks(self):
|
||||
self.Links.clear()
|
||||
allLinks = cursor.execute("SELECT * FROM PeerShareLinks WHERE ExpireDate IS NULL OR ExpireDate > datetime('now', 'localtime')").fetchall()
|
||||
for link in allLinks:
|
||||
self.Links.append(*link)
|
||||
self.Links.append(PeerShareLink(*link))
|
||||
|
||||
def getLink(self, Configuration: str, Peer: str):
|
||||
def getLink(self, Configuration: str, Peer: str) -> list[PeerShareLink]:
|
||||
return list(filter(lambda x : x.Configuration == Configuration and x.Peer == Peer, self.Links))
|
||||
|
||||
def getLink(self, ShareID: str):
|
||||
def getLinkByID(self, ShareID: str) -> list[PeerShareLink]:
|
||||
return list(filter(lambda x : x.ShareID == ShareID, self.Links))
|
||||
|
||||
def addLink(self, Configuration: str, Peer: str, ExpireDate: datetime = None) -> tuple[bool, message]:
|
||||
def addLink(self, Configuration: str, Peer: str, ExpireDate: datetime = None) -> tuple[bool, str]:
|
||||
try:
|
||||
newShareID = str(uuid.uuid4())
|
||||
if len(self.getLink(Configuration, Peer)) > 0:
|
||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE Configuration = ? AND Peer = ?", (Configuration, Peer, ))
|
||||
cursor.execute("INSERT INTO PeerShareLinks VALUES (?, ?, ?, ?)", (newShareID, Configuration, Peer, ExpireDate, ))
|
||||
|
||||
if ExpireDate is not None:
|
||||
ExpireDate = datetime.strptime(ExpireDate, '%Y-%m-%d %H:%M:%S')
|
||||
|
||||
cursor.execute("INSERT INTO PeerShareLinks (ShareID, Configuration, Peer, ExpireDate) VALUES (?, ?, ?, ?)", (newShareID, Configuration, Peer, ExpireDate, ))
|
||||
sqldb.commit()
|
||||
self.__getSharedLinks()
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
return True
|
||||
return True, newShareID
|
||||
|
||||
def updateLinkExpireDate(self, ShareID, ExpireDate):
|
||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE ShareID = ?", (ShareID, ))
|
||||
sqldb.commit()
|
||||
self.__getSharedLinks()
|
||||
def updateLinkExpireDate(self, ShareID, ExpireDate: datetime = None) -> tuple[bool, str]:
|
||||
try:
|
||||
if ExpireDate is None:
|
||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = datetime('now', 'localtime') WHERE ShareID = ?", (ShareID, ))
|
||||
else:
|
||||
cursor.execute("UPDATE PeerShareLinks SET ExpireDate = ? WHERE ShareID = ?", (ShareID, datetime.strptime(ExpireDate, '%Y-%m-%d %H:%M:%S'), ))
|
||||
sqldb.commit()
|
||||
self.__getSharedLinks()
|
||||
return True
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
|
||||
|
||||
@ -876,10 +893,13 @@ class Peer:
|
||||
self.remote_endpoint = tableData["remote_endpoint"]
|
||||
self.preshared_key = tableData["preshared_key"]
|
||||
self.jobs: list[PeerJob] = []
|
||||
self.ShareLink: list[PeerShareLink] = []
|
||||
self.getJobs()
|
||||
self.getShareLink()
|
||||
|
||||
def toJson(self):
|
||||
self.getJobs()
|
||||
self.getShareLink()
|
||||
return self.__dict__
|
||||
|
||||
def __repr__(self):
|
||||
@ -978,8 +998,10 @@ PersistentKeepalive = {str(self.keepalive)}
|
||||
|
||||
def getJobs(self):
|
||||
self.jobs = AllPeerJobs.searchJob(self.configuration.Name, self.id)
|
||||
# print(AllPeerJobs.searchJob(self.configuration.Name, self.id))
|
||||
|
||||
def getShareLink(self):
|
||||
self.ShareLink = AllPeerShareLinks.getLink(self.configuration.Name, self.id)
|
||||
|
||||
# Regex Match
|
||||
def regex_match(regex, text):
|
||||
pattern = re.compile(regex)
|
||||
@ -1551,6 +1573,38 @@ def API_restrictPeers(configName: str) -> ResponseObject:
|
||||
return configuration.restrictPeers(peers)
|
||||
return ResponseObject(False, "Configuration does not exist")
|
||||
|
||||
@app.route('/api/sharePeer/create', methods=['POST'])
|
||||
def API_sharePeer_create():
|
||||
data: dict[str, str] = request.get_json()
|
||||
Configuration = data.get('Configuration')
|
||||
Peer = data.get('Peer')
|
||||
ExpireDate = data.get('ExpireDate')
|
||||
if Configuration is None or Peer is None:
|
||||
return ResponseObject(False, "Please specify configuration and peer")
|
||||
activeLink = AllPeerShareLinks.getLink(Configuration, Peer)
|
||||
if len(activeLink) > 0:
|
||||
return ResponseObject(False, "This peer is already sharing, please stop sharing first.")
|
||||
status, message = AllPeerShareLinks.addLink(Configuration, Peer, ExpireDate)
|
||||
if not status:
|
||||
return ResponseObject(status, message)
|
||||
return ResponseObject(data=AllPeerShareLinks.getLinkByID(message))
|
||||
|
||||
@app.route('/api/sharePeer/update', methods=['POST'])
|
||||
def API_sharePeer_update():
|
||||
data: dict[str, str] = request.get_json()
|
||||
ShareID: str = data.get("ShareID")
|
||||
ExpireDate: str = data.get("ExpireDate")
|
||||
|
||||
if ShareID is None:
|
||||
return ResponseObject(False, "Please specify ShareID")
|
||||
|
||||
if len(AllPeerShareLinks.getLinkByID(ShareID)) == 0:
|
||||
return ResponseObject(False, "ShareID does not exist")
|
||||
|
||||
status, message = AllPeerShareLinks.updateLinkExpireDate(ShareID, ExpireDate)
|
||||
if not status:
|
||||
return ResponseObject(status, message)
|
||||
return ResponseObject(data=AllPeerShareLinks.getLinkByID(ShareID))
|
||||
|
||||
@app.route('/api/allowAccessPeers/<configName>', methods=['POST'])
|
||||
def API_allowAccessPeers(configName: str) -> ResponseObject:
|
||||
@ -1949,6 +2003,7 @@ sqldb.row_factory = sqlite3.Row
|
||||
cursor = sqldb.cursor()
|
||||
DashboardConfig = DashboardConfig()
|
||||
|
||||
AllPeerShareLinks: PeerShareLinks = PeerShareLinks()
|
||||
AllPeerJobs: PeerJobs = PeerJobs()
|
||||
JobLogger: PeerJobLogger = PeerJobLogger()
|
||||
DashboardLogger: DashboardLogger = DashboardLogger()
|
||||
|
24
src/static/app/package-lock.json
generated
24
src/static/app/package-lock.json
generated
@ -8,6 +8,7 @@
|
||||
"name": "app",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@vuepic/vue-datepicker": "^9.0.1",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@vueuse/shared": "^10.9.0",
|
||||
"animate.css": "^4.1.1",
|
||||
@ -721,6 +722,20 @@
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.29.tgz",
|
||||
"integrity": "sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA=="
|
||||
},
|
||||
"node_modules/@vuepic/vue-datepicker": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-9.0.1.tgz",
|
||||
"integrity": "sha512-5sSdwib5cY8cE4Y7SCh+Zemfp+U/m6BDcgaPwd5Vmdv5LAASyV0wugn9sTb6NWX0sIQEdrGDl/RmD9EjcIke3A==",
|
||||
"dependencies": {
|
||||
"date-fns": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz",
|
||||
@ -937,6 +952,15 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.12",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vuepic/vue-datepicker": "^9.0.1",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@vueuse/shared": "^10.9.0",
|
||||
"animate.css": "^4.1.1",
|
||||
|
@ -86,6 +86,7 @@ export default {
|
||||
@setting="this.$emit('setting')"
|
||||
@jobs="this.$emit('jobs')"
|
||||
@refresh="this.$emit('refresh')"
|
||||
@share="this.$emit('share')"
|
||||
:Peer="Peer"
|
||||
v-if="this.subMenuOpened"
|
||||
ref="target"
|
||||
|
@ -40,6 +40,7 @@ import PeerJobs from "@/components/configurationComponents/peerJobs.vue";
|
||||
import PeerJobsAllModal from "@/components/configurationComponents/peerJobsAllModal.vue";
|
||||
import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogsModal.vue";
|
||||
import {ref} from "vue";
|
||||
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
|
||||
|
||||
Chart.register(
|
||||
ArcElement,
|
||||
@ -70,6 +71,7 @@ Chart.register(
|
||||
export default {
|
||||
name: "peerList",
|
||||
components: {
|
||||
PeerShareLinkModal,
|
||||
PeerJobsLogsModal,
|
||||
PeerJobsAllModal, PeerJobs, PeerCreate, PeerQRCode, PeerSettings, PeerSearch, Peer, Line, Bar},
|
||||
setup(){
|
||||
@ -131,6 +133,10 @@ export default {
|
||||
},
|
||||
peerScheduleJobsLogs: {
|
||||
modalOpen: false
|
||||
},
|
||||
peerShare:{
|
||||
modalOpen: false,
|
||||
selectedPeer: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -141,26 +147,21 @@ export default {
|
||||
'$route': {
|
||||
immediate: true,
|
||||
handler(){
|
||||
console.log(this.dashboardConfigurationStore.Peers.RefreshInterval)
|
||||
clearInterval(this.dashboardConfigurationStore.Peers.RefreshInterval);
|
||||
console.log(this.dashboardConfigurationStore.Peers.RefreshInterval)
|
||||
|
||||
this.loading = true;
|
||||
let id = this.$route.params.id;
|
||||
this.configurationInfo = [];
|
||||
this.configurationPeers = [];
|
||||
if (id){
|
||||
this.getPeers(id)
|
||||
console.log("Changed..")
|
||||
this.setPeerInterval();
|
||||
}
|
||||
}
|
||||
},
|
||||
'dashboardConfigurationStore.Configuration.Server.dashboard_refresh_interval'(){
|
||||
console.log("Changed?")
|
||||
clearInterval(this.dashboardConfigurationStore.Peers.RefreshInterval);
|
||||
this.setPeerInterval();
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeRouteLeave(){
|
||||
clearInterval(this.dashboardConfigurationStore.Peers.RefreshInterval);
|
||||
@ -248,7 +249,6 @@ export default {
|
||||
this.dashboardConfigurationStore.Peers.RefreshInterval = setInterval(() => {
|
||||
this.getPeers()
|
||||
}, parseInt(this.dashboardConfigurationStore.Configuration.Server.dashboard_refresh_interval))
|
||||
console.log(this.dashboardConfigurationStore.Peers.RefreshInterval)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
@ -548,7 +548,7 @@ export default {
|
||||
:key="peer.id"
|
||||
v-for="peer in this.searchPeers">
|
||||
<Peer :Peer="peer"
|
||||
|
||||
@share="this.peerShare.selectedPeer = peer.id; this.peerShare.modalOpen = true;"
|
||||
@refresh="this.getPeers()"
|
||||
@jobs="peerScheduleJobs.modalOpen = true; peerScheduleJobs.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)"
|
||||
@setting="peerSetting.modalOpen = true; peerSetting.selectedPeer = this.configurationPeers.find(x => x.id === peer.id)"
|
||||
@ -595,6 +595,12 @@ export default {
|
||||
>
|
||||
</PeerJobsLogsModal>
|
||||
</Transition>
|
||||
<Transition name="zoom">
|
||||
<PeerShareLinkModal
|
||||
v-if="this.peerShare.modalOpen"
|
||||
@close="this.peerShare.modalOpen = false; this.peerShare.selectedPeer = undefined;"
|
||||
:peer="this.configurationPeers.find(x => x.id === this.peerShare.selectedPeer)"></PeerShareLinkModal>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -123,7 +123,7 @@ export default {
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item d-flex" role="button">
|
||||
<a class="dropdown-item d-flex" role="button" @click="this.$emit('share')">
|
||||
<i class="me-auto bi bi-share"></i> Share
|
||||
</a>
|
||||
</li>
|
||||
|
@ -0,0 +1,124 @@
|
||||
<script>
|
||||
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||
import {fetchPost} from "@/utilities/fetch.js";
|
||||
import dayjs from "dayjs";
|
||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
|
||||
|
||||
export default {
|
||||
name: "peerShareLinkModal",
|
||||
props: {
|
||||
peer: Object
|
||||
},
|
||||
components: {
|
||||
VueDatePicker
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
dataCopy: undefined,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
setup(){
|
||||
const store = DashboardConfigurationStore();
|
||||
return {store}
|
||||
},
|
||||
mounted() {
|
||||
this.dataCopy = JSON.parse(JSON.stringify(this.peer.ShareLink)).at(0);
|
||||
},
|
||||
methods: {
|
||||
startSharing(){
|
||||
this.loading = true;
|
||||
fetchPost("/api/sharePeer/create", {
|
||||
Configuration: this.peer.configuration.Name,
|
||||
Peer: this.peer.id,
|
||||
ExpireDate: dayjs().add(30, 'd').format("YYYY-MM-DD hh:mm:ss")
|
||||
}, (res) => {
|
||||
if (res.status){
|
||||
this.peer.ShareLink = res.data;
|
||||
this.dataCopy = res.data;
|
||||
this.store.newMessage("Server", "Share link created successfully", "success")
|
||||
}else{
|
||||
this.store.newMessage("Server",
|
||||
"Share link failed to create. Reason: " + res.message, "danger")
|
||||
|
||||
}
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
updateLinkExpireDate(){
|
||||
fetchPost("/api/sharePeer/update", this.dataCopy, (res) => {
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getUrl(){
|
||||
return window.location.origin
|
||||
+ window.location.pathname
|
||||
+ this.$router.resolve(
|
||||
{path: "/share", query: {"ShareID": this.dataCopy.ShareID}}).href;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'dataCopy.ExpireDate'(){
|
||||
this.updateLinkExpireDate()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
|
||||
<div class="container d-flex h-100 w-100">
|
||||
<div class="m-auto modal-dialog-centered dashboardModal" style="width: 500px">
|
||||
<div class="card rounded-3 shadow flex-grow-1">
|
||||
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4">
|
||||
<h4 class="mb-0">Share Peer</h4>
|
||||
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
||||
</div>
|
||||
<div class="card-body px-4 pb-4" v-if="this.peer.ShareLink">
|
||||
<div v-if="!this.dataCopy">
|
||||
<h6 class="mb-3 text-muted">
|
||||
Currently the peer is not sharing
|
||||
</h6>
|
||||
<button
|
||||
@click="this.startSharing()"
|
||||
:disabled="this.loading"
|
||||
class="w-100 btn bg-success-subtle text-success-emphasis border-1 border-success-subtle rounded-3 shadow-sm">
|
||||
<span :class="{'animate__animated animate__flash animate__infinite animate__slower': this.loading}">
|
||||
<i class="bi bi-send-fill me-2" ></i>
|
||||
</span>
|
||||
{{this.loading ? "Sharing...":"Start Sharing"}}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="d-flex gap-2 mb-4">
|
||||
<i class="bi bi-link-45deg"></i>
|
||||
<a :href="this.getUrl"
|
||||
class="text-decoration-none" target="_blank">
|
||||
{{ getUrl }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<small>
|
||||
<i class="bi bi-calendar me-2"></i>
|
||||
Expire Date
|
||||
</small>
|
||||
<VueDatePicker v-model="this.dataCopy.ExpireDate" time-picker-inline
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
:dark="this.store.Configuration.Server.dashboard_theme === 'dark'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -3,6 +3,7 @@ import 'bootstrap/dist/css/bootstrap.css'
|
||||
import 'bootstrap/dist/js/bootstrap.js'
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||
import 'animate.css/animate.compat.css'
|
||||
import '@vuepic/vue-datepicker/dist/main.css'
|
||||
|
||||
import {createApp, markRaw} from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
@ -1,3 +1,8 @@
|
||||
*,
|
||||
.dp__input{
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user