mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-08-04 19:25:13 -04:00
add port scan
This commit is contained in:
@@ -34,11 +34,11 @@ Open up [localhost:5173/](localhost:5173/)
|
||||
- [ ] form for adding new devices
|
||||
- [ ] add per device settings
|
||||
- [x] theme toggle button
|
||||
- [ ] add device ports to cards
|
||||
- [x] add device ports to cards
|
||||
|
||||
- backend
|
||||
|
||||
- [ ] make sure ping works
|
||||
- [x] make sure ping works
|
||||
- [ ] make sure arp works
|
||||
- [ ] make sure wake works
|
||||
- [ ] remove nmap?
|
||||
|
||||
@@ -42,7 +42,17 @@ func RunCron(app *pocketbase.PocketBase) {
|
||||
// init cronjob
|
||||
c := cron.New()
|
||||
c.AddFunc(fmt.Sprintf("@every %s", interval), func() {
|
||||
// expand ports field
|
||||
expandFetchFunc := func(c *models.Collection, ids []string) ([]*models.Record, error) {
|
||||
return app.Dao().FindRecordsByIds(c.Id, ids, nil)
|
||||
}
|
||||
merr := app.Dao().ExpandRecords(Devices, []string{"ports"}, expandFetchFunc)
|
||||
if len(merr) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, device := range Devices {
|
||||
// ping
|
||||
go func(device *models.Record) {
|
||||
oldStatus := device.Get("status")
|
||||
newStatus := networking.PingDevice(device)
|
||||
@@ -58,6 +68,23 @@ func RunCron(app *pocketbase.PocketBase) {
|
||||
}
|
||||
}
|
||||
}(device)
|
||||
|
||||
// scan ports
|
||||
go func(device *models.Record) {
|
||||
ports, err := app.Dao().FindRecordsByIds("ports", device.GetStringSlice("ports"))
|
||||
if err != nil {
|
||||
logger.Error.Println(err)
|
||||
}
|
||||
for _, port := range ports {
|
||||
isUp := networking.CheckPort(device.GetString("ip"), port.GetString("number"))
|
||||
if isUp != port.GetBool("status") {
|
||||
port.Set("status", isUp)
|
||||
app.Dao().SaveRecord(port)
|
||||
device.RefreshUpdated()
|
||||
app.Dao().SaveRecord(device)
|
||||
}
|
||||
}
|
||||
}(device)
|
||||
}
|
||||
})
|
||||
c.Run()
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `[
|
||||
{
|
||||
"id": "z5lghx2r3tm45n1",
|
||||
"created": "2023-01-14 21:50:42.797Z",
|
||||
"updated": "2023-01-14 21:50:42.797Z",
|
||||
"name": "devices",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "tiqcmnjo",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "1si6ajha",
|
||||
"name": "ip",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "fyqmpon6",
|
||||
"name": "mac",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "s8c5z7n0",
|
||||
"name": "netmask",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "gdctb8hj",
|
||||
"name": "link",
|
||||
"type": "url",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"exceptDomains": null,
|
||||
"onlyDomains": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "ilrwvlev",
|
||||
"name": "port",
|
||||
"type": "relation",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSelect": null,
|
||||
"collectionId": "cti4l8f4mz8df3r",
|
||||
"cascadeDelete": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "qqvyfrex",
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "1a7yrwo9",
|
||||
"name": "shutdown_cmd",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": "",
|
||||
"updateRule": "",
|
||||
"deleteRule": "",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"id": "cti4l8f4mz8df3r",
|
||||
"created": "2023-01-14 21:50:42.797Z",
|
||||
"updated": "2023-01-14 21:50:42.797Z",
|
||||
"name": "ports",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "8nwuncgg",
|
||||
"name": "number",
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": 65535
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "o0he3pu6",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": "",
|
||||
"updateRule": "",
|
||||
"deleteRule": "",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"id": "nmj3ko20gzkg8n3",
|
||||
"created": "2023-01-14 21:50:42.797Z",
|
||||
"updated": "2023-01-14 21:50:42.797Z",
|
||||
"name": "settings",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "ysutxavs",
|
||||
"name": "interval",
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": 1,
|
||||
"max": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": null,
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
}
|
||||
]`
|
||||
|
||||
collections := []*models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collections); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).ImportCollections(collections, true, nil)
|
||||
}, func(db dbx.Builder) error {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add
|
||||
new_wake := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "kzvdbbws",
|
||||
"name": "wake",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}`), new_wake)
|
||||
collection.Schema.AddField(new_wake)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("kzvdbbws")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update
|
||||
edit_shutdown := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "1a7yrwo9",
|
||||
"name": "shutdown",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}`), edit_shutdown)
|
||||
collection.Schema.AddField(edit_shutdown)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update
|
||||
edit_shutdown := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "1a7yrwo9",
|
||||
"name": "shutdown_cmd",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}`), edit_shutdown)
|
||||
collection.Schema.AddField(edit_shutdown)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
163
backend/migrations/1674429704_created_devices.go
Normal file
163
backend/migrations/1674429704_created_devices.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "z5lghx2r3tm45n1",
|
||||
"created": "2023-01-22 23:21:44.280Z",
|
||||
"updated": "2023-01-22 23:21:44.280Z",
|
||||
"name": "devices",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "tiqcmnjo",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "1si6ajha",
|
||||
"name": "ip",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "fyqmpon6",
|
||||
"name": "mac",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "s8c5z7n0",
|
||||
"name": "netmask",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "qqvyfrex",
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "ilrwvlev",
|
||||
"name": "ports",
|
||||
"type": "relation",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSelect": null,
|
||||
"collectionId": "cti4l8f4mz8df3r",
|
||||
"cascadeDelete": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "gdctb8hj",
|
||||
"name": "link",
|
||||
"type": "url",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"exceptDomains": null,
|
||||
"onlyDomains": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "1a7yrwo9",
|
||||
"name": "shutdown",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "kzvdbbws",
|
||||
"name": "wake",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": "",
|
||||
"updateRule": "",
|
||||
"deleteRule": "",
|
||||
"options": {}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
})
|
||||
}
|
||||
81
backend/migrations/1674429704_created_ports.go
Normal file
81
backend/migrations/1674429704_created_ports.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "cti4l8f4mz8df3r",
|
||||
"created": "2023-01-22 23:21:44.280Z",
|
||||
"updated": "2023-01-22 23:21:44.280Z",
|
||||
"name": "ports",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "8nwuncgg",
|
||||
"name": "number",
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": 65535
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "o0he3pu6",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "w0bh39gv",
|
||||
"name": "status",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": "",
|
||||
"updateRule": "",
|
||||
"deleteRule": "",
|
||||
"options": {}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("cti4l8f4mz8df3r")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
})
|
||||
}
|
||||
59
backend/migrations/1674429704_created_settings.go
Normal file
59
backend/migrations/1674429704_created_settings.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "nmj3ko20gzkg8n3",
|
||||
"created": "2023-01-22 23:21:44.281Z",
|
||||
"updated": "2023-01-22 23:21:44.281Z",
|
||||
"name": "settings",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "ysutxavs",
|
||||
"name": "interval",
|
||||
"type": "number",
|
||||
"required": true,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": 1,
|
||||
"max": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": null,
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("nmj3ko20gzkg8n3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
})
|
||||
}
|
||||
90
backend/migrations/1674429704_deleted_users.go
Normal file
90
backend/migrations/1674429704_deleted_users.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "_pb_users_auth_",
|
||||
"created": "2023-01-22 23:21:16.599Z",
|
||||
"updated": "2023-01-22 23:21:16.600Z",
|
||||
"name": "users",
|
||||
"type": "auth",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "users_name",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "users_avatar",
|
||||
"name": "avatar",
|
||||
"type": "file",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSelect": 1,
|
||||
"maxSize": 5242880,
|
||||
"mimeTypes": [
|
||||
"image/jpg",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/gif",
|
||||
"image/webp"
|
||||
],
|
||||
"thumbs": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": "id = @request.auth.id",
|
||||
"viewRule": "id = @request.auth.id",
|
||||
"createRule": "",
|
||||
"updateRule": "id = @request.auth.id",
|
||||
"deleteRule": "id = @request.auth.id",
|
||||
"options": {
|
||||
"allowEmailAuth": true,
|
||||
"allowOAuth2Auth": true,
|
||||
"allowUsernameAuth": true,
|
||||
"exceptEmailDomains": null,
|
||||
"manageRule": null,
|
||||
"minPasswordLength": 8,
|
||||
"onlyEmailDomains": null,
|
||||
"requireEmail": false
|
||||
}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package networking
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/go-ping/ping"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
@@ -31,3 +33,16 @@ func PingDevice(device *models.Record) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func CheckPort(host string, port string) bool {
|
||||
timeout := 500 * time.Millisecond
|
||||
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if conn != nil {
|
||||
defer conn.Close()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^1.0.1",
|
||||
"@sveltejs/kit": "^1.1.1",
|
||||
"@sveltejs/adapter-static": "^1.0.5",
|
||||
"@sveltejs/kit": "^1.2.2",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
@@ -27,7 +27,7 @@
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"bootstrap": "5.3.0-alpha1",
|
||||
"date-fns": "^2.29.3",
|
||||
"pocketbase": "^0.10.0",
|
||||
"pocketbase": "^0.10.1",
|
||||
"sass": "^1.57.1",
|
||||
"svelte-fa": "^3.0.3"
|
||||
}
|
||||
|
||||
50
frontend/pnpm-lock.yaml
generated
50
frontend/pnpm-lock.yaml
generated
@@ -3,14 +3,14 @@ lockfileVersion: 5.4
|
||||
specifiers:
|
||||
'@fortawesome/free-solid-svg-icons': ^6.2.1
|
||||
'@popperjs/core': ^2.11.6
|
||||
'@sveltejs/adapter-static': ^1.0.1
|
||||
'@sveltejs/kit': ^1.1.1
|
||||
'@sveltejs/adapter-static': ^1.0.5
|
||||
'@sveltejs/kit': ^1.2.2
|
||||
bootstrap: 5.3.0-alpha1
|
||||
date-fns: ^2.29.3
|
||||
eslint: ^8.32.0
|
||||
eslint-config-prettier: ^8.6.0
|
||||
eslint-plugin-svelte3: ^4.0.0
|
||||
pocketbase: ^0.10.0
|
||||
pocketbase: ^0.10.1
|
||||
prettier: ^2.8.3
|
||||
prettier-plugin-svelte: ^2.9.0
|
||||
sass: ^1.57.1
|
||||
@@ -24,13 +24,13 @@ dependencies:
|
||||
'@popperjs/core': 2.11.6
|
||||
bootstrap: 5.3.0-alpha1_@popperjs+core@2.11.6
|
||||
date-fns: 2.29.3
|
||||
pocketbase: 0.10.0
|
||||
pocketbase: 0.10.1
|
||||
sass: 1.57.1
|
||||
svelte-fa: 3.0.3
|
||||
|
||||
devDependencies:
|
||||
'@sveltejs/adapter-static': 1.0.4_@sveltejs+kit@1.1.1
|
||||
'@sveltejs/kit': 1.1.1_svelte@3.55.1+vite@4.0.4
|
||||
'@sveltejs/adapter-static': 1.0.5_@sveltejs+kit@1.2.2
|
||||
'@sveltejs/kit': 1.2.2_svelte@3.55.1+vite@4.0.4
|
||||
eslint: 8.32.0
|
||||
eslint-config-prettier: 8.6.0_eslint@8.32.0
|
||||
eslint-plugin-svelte3: 4.0.0_tmo5zkisvhu6htudosk5k7m6pu
|
||||
@@ -324,16 +324,16 @@ packages:
|
||||
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
|
||||
dev: false
|
||||
|
||||
/@sveltejs/adapter-static/1.0.4_@sveltejs+kit@1.1.1:
|
||||
resolution: {integrity: sha512-L6kGg19MBHW3kv3GWAPl9tJo3ohNM+dcj9Yq1U1XVu0J0MKrusyCWQ62XOfxFgS6T8Fq0KYJ5NSSAPGppvX4xA==}
|
||||
/@sveltejs/adapter-static/1.0.5_@sveltejs+kit@1.2.2:
|
||||
resolution: {integrity: sha512-W5jbgvy9sbYEHs27NQOSFEun+zQwdcL4kpk5qc2kSHl8cKsP5wfXuWDTDRmD1Co40aFcesi5Az5ZzdnPI8KCVg==}
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.0.0
|
||||
dependencies:
|
||||
'@sveltejs/kit': 1.1.1_svelte@3.55.1+vite@4.0.4
|
||||
'@sveltejs/kit': 1.2.2_svelte@3.55.1+vite@4.0.4
|
||||
dev: true
|
||||
|
||||
/@sveltejs/kit/1.1.1_svelte@3.55.1+vite@4.0.4:
|
||||
resolution: {integrity: sha512-5hZef6yTqiLm8fLMFD78udJI3pG9ptSndg3NNmDqxv5fS9KFABkASQwnWB25Pf1HkPNqvL+x4Tl8kyW1N8thKQ==}
|
||||
/@sveltejs/kit/1.2.2_svelte@3.55.1+vite@4.0.4:
|
||||
resolution: {integrity: sha512-aZUjAZ/6gWEYFQDrDNINuvOi6VxlG86kCcIDRWDIFJjI38Ueieo1fySb0j0d2VkQVrYXU7VqjTVMBZFix+hByA==}
|
||||
engines: {node: ^16.14 || >=18}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
@@ -354,7 +354,7 @@ packages:
|
||||
sirv: 2.0.2
|
||||
svelte: 3.55.1
|
||||
tiny-glob: 0.2.9
|
||||
undici: 5.15.0
|
||||
undici: 5.15.1
|
||||
vite: 4.0.4_sass@1.57.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -699,7 +699,7 @@ packages:
|
||||
imurmurhash: 0.1.4
|
||||
is-glob: 4.0.3
|
||||
is-path-inside: 3.0.3
|
||||
js-sdsl: 4.2.0
|
||||
js-sdsl: 4.3.0
|
||||
js-yaml: 4.1.0
|
||||
json-stable-stringify-without-jsonify: 1.0.1
|
||||
levn: 0.4.1
|
||||
@@ -944,8 +944,8 @@ packages:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/js-sdsl/4.2.0:
|
||||
resolution: {integrity: sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==}
|
||||
/js-sdsl/4.3.0:
|
||||
resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==}
|
||||
dev: true
|
||||
|
||||
/js-yaml/4.1.0:
|
||||
@@ -1122,8 +1122,8 @@ packages:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
/pocketbase/0.10.0:
|
||||
resolution: {integrity: sha512-OWcPRcOPNiTqek5wkf56mCmkox4w5/h1x+ySBNqzQ0Ux7ztEv3aq3Gr91bwn3VcXN7o48XVbKny7A922hNIbQw==}
|
||||
/pocketbase/0.10.1:
|
||||
resolution: {integrity: sha512-FMBhF+9o2AmdKJYbfz2qunnk4Q5/efYMRcukdQF49UfhsIuaSYl39fSPN1l880bYI4XAvDDeySAjK1MlxrK37A==}
|
||||
dev: false
|
||||
|
||||
/postcss/8.4.21:
|
||||
@@ -1156,8 +1156,8 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/punycode/2.2.0:
|
||||
resolution: {integrity: sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==}
|
||||
/punycode/2.3.0:
|
||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
@@ -1209,8 +1209,8 @@ packages:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup/3.10.0:
|
||||
resolution: {integrity: sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==}
|
||||
/rollup/3.10.1:
|
||||
resolution: {integrity: sha512-3Er+yel3bZbZX1g2kjVM+FW+RUWDxbG87fcqFM5/9HbPCTpbVp6JOLn7jlxnNlbu7s/N/uDA4EV/91E2gWnxzw==}
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
@@ -1431,8 +1431,8 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/undici/5.15.0:
|
||||
resolution: {integrity: sha512-wCAZJDyjw9Myv+Ay62LAoB+hZLPW9SmKbQkbHIhMw/acKSlpn7WohdMUc/Vd4j1iSMBO0hWwU8mjB7a5p5bl8g==}
|
||||
/undici/5.15.1:
|
||||
resolution: {integrity: sha512-XLk8g0WAngdvFqTI+VKfBtM4YWXgdxkf1WezC771Es0Dd+Pm1KmNx8t93WTC+Hh9tnghmVxkclU1HN+j+CvIUA==}
|
||||
engines: {node: '>=12.18'}
|
||||
dependencies:
|
||||
busboy: 1.6.0
|
||||
@@ -1441,7 +1441,7 @@ packages:
|
||||
/uri-js/4.4.1:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
dependencies:
|
||||
punycode: 2.2.0
|
||||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/vite/4.0.4_sass@1.57.1:
|
||||
@@ -1472,7 +1472,7 @@ packages:
|
||||
esbuild: 0.16.17
|
||||
postcss: 8.4.21
|
||||
resolve: 1.22.1
|
||||
rollup: 3.10.0
|
||||
rollup: 3.10.1
|
||||
sass: 1.57.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { dev } from '$app/environment';
|
||||
import { parseISO, formatDistance } from 'date-fns';
|
||||
import { faPowerOff, faEllipsisVertical } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPowerOff, faEllipsisVertical, faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
|
||||
export let device;
|
||||
@@ -14,6 +14,10 @@
|
||||
function wake() {
|
||||
fetch(`${dev ? 'http://127.0.0.1:8090' : ''}/api/upsnap/wake/${device.id}`);
|
||||
}
|
||||
|
||||
function sortPorts(a, b) {
|
||||
return a.number - b.number;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 g-4">
|
||||
@@ -49,8 +53,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<p class="m-0 fw-bold fs-5">{device.name}</p>
|
||||
<p class="text-muted">{device.ip}</p>
|
||||
<p class="m-0 text-muted">
|
||||
<p class="text-muted mb-2">{device.ip}</p>
|
||||
{#if device?.expand?.ports}
|
||||
<div class="mb-2">
|
||||
{#each device.expand.ports.sort(sortPorts) as port}
|
||||
<p class="m-0">
|
||||
<Fa icon={faCircle} class="me-1 {port.status ? 'port-up' : 'port-down'}" />{port.name}
|
||||
<span class="text-muted">({port.number})</span>
|
||||
</p>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<p class="text-muted m-0">
|
||||
{formatDistance(parseISO(device.updated), now, {
|
||||
includeSeconds: true,
|
||||
addSuffix: true
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { theme } from '@stores/themestore';
|
||||
import { theme } from '@stores/theme';
|
||||
import { faSun, faMoon, faCircleHalfStroke, faBrush } from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
import('bootstrap/js/dist/dropdown');
|
||||
|
||||
onMount(() => {
|
||||
import('bootstrap/js/dist/dropdown');
|
||||
})
|
||||
</script>
|
||||
|
||||
<nav class="navbar navbar-expand">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import Navbar from '@components/Navbar.svelte';
|
||||
import Transition from '@components/Transition.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { theme } from '@stores/themestore';
|
||||
import { theme } from '@stores/theme';
|
||||
|
||||
let preferesDark;
|
||||
|
||||
|
||||
@@ -12,14 +12,33 @@
|
||||
});
|
||||
|
||||
// get all devices in pocketbase
|
||||
const result = await pb.collection('devices').getFullList();
|
||||
const result = await pb.collection('devices').getFullList(200, {
|
||||
expand: 'ports'
|
||||
});
|
||||
result.forEach((device) => {
|
||||
devices[device.id] = device;
|
||||
});
|
||||
|
||||
// subscribe to database events
|
||||
pb.collection('devices').subscribe('*', function (e) {
|
||||
devices[e.record.id] = e.record;
|
||||
pb.collection('devices').subscribe('*', async (e) => {
|
||||
if (e.action === 'create') {
|
||||
devices[e.record.id] = e.record;
|
||||
} else if (e.action === 'update') {
|
||||
const device = await pb.collection('devices').getOne(e.record.id, {
|
||||
expand: 'ports'
|
||||
})
|
||||
devices[device.id] = device
|
||||
} else if (e.action === 'delete') {
|
||||
delete devices[e.record.id]
|
||||
}
|
||||
});
|
||||
pb.collection('ports').subscribe('*', async (e) => {
|
||||
if (e.action === 'update') {
|
||||
const device = await pb.collection('devices').getFirstListItem(`ports.id ?= "${e.record.id}"`, {
|
||||
expand: 'ports'
|
||||
})
|
||||
devices[device.id] = device
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -33,28 +33,22 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let createdPorts = {};
|
||||
// loop devices
|
||||
for (let index = 0; index < data.length; index++) {
|
||||
const device = data[index];
|
||||
|
||||
// create ports
|
||||
let thisDevicePorts = [];
|
||||
for (let index = 0; index < device.ports.length; index++) {
|
||||
// keep track of already created ports
|
||||
const port = device.ports[index];
|
||||
if (createdPorts[port.number] === undefined) {
|
||||
const record = await pb.collection('ports').create(
|
||||
{
|
||||
name: port.name,
|
||||
number: port.number
|
||||
},
|
||||
{ $autoCancel: false }
|
||||
);
|
||||
createdPorts[port.number] = record;
|
||||
thisDevicePorts.push(record.id);
|
||||
} else {
|
||||
thisDevicePorts.push(createdPorts[port.number].id);
|
||||
}
|
||||
const record = await pb.collection('ports').create(
|
||||
{
|
||||
name: port.name,
|
||||
number: port.number
|
||||
},
|
||||
{ $autoCancel: false }
|
||||
);
|
||||
thisDevicePorts.push(record.id);
|
||||
}
|
||||
|
||||
// create device
|
||||
@@ -64,7 +58,7 @@
|
||||
ip: device.ip,
|
||||
mac: device.mac,
|
||||
netmask: device.netmask,
|
||||
port: thisDevicePorts,
|
||||
ports: thisDevicePorts,
|
||||
link: device.link,
|
||||
wake: device.wake,
|
||||
shutdown: device.shutdown
|
||||
|
||||
@@ -56,7 +56,7 @@ section {
|
||||
}
|
||||
}
|
||||
|
||||
.text-success {
|
||||
.text-success, .port-up {
|
||||
color: $teal-500 !important;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ section {
|
||||
color: $yellow !important;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
.text-danger, .port-down {
|
||||
color: #ef476f !important;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user