--wip-- [skip ci]
This commit is contained in:
parent
ccf3981d8d
commit
7a8b904852
10 changed files with 282 additions and 191 deletions
|
|
@ -1,111 +1,112 @@
|
|||
{
|
||||
"credentials": {
|
||||
"club-assistant": {
|
||||
"username": "club-assistant",
|
||||
"password": "clubmiau"
|
||||
},
|
||||
"dooris-hauptraum": {
|
||||
"username": "dooris-hauptraum",
|
||||
"password": "doorimiau"
|
||||
}
|
||||
},
|
||||
"dynamic": {
|
||||
"sensors": {
|
||||
"temperature": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "°C",
|
||||
"location": "Hauptraum",
|
||||
"name": "Kueche",
|
||||
"description": "Sensor im Ofen"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "°C",
|
||||
"location": "Hauptraum",
|
||||
"description": "Sensor im Hauptraum"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
],
|
||||
"humidity": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "%",
|
||||
"location": "Hauptraum",
|
||||
"name": "Kueche",
|
||||
"description": "Sensor im Wasserhahn"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
],
|
||||
"beverage_supply": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "btl"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"state": {
|
||||
"open": {
|
||||
"allowed_credentials": [
|
||||
"dooris-hauptraum"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"api_compatibility": [
|
||||
"14"
|
||||
],
|
||||
"space": "CCCHH",
|
||||
"logo": "https://hamburg.ccc.de/images/logo.svg",
|
||||
"ext_ccc": "erfa",
|
||||
"url": "https://hamburg.ccc.de/",
|
||||
"location": {
|
||||
"address": "Zeiseweg 9, 22765 Hamburg, Germany",
|
||||
"lon": 9.94444,
|
||||
"lat": 53.5584
|
||||
},
|
||||
"contact": {
|
||||
"phone": "+49 40 23830150",
|
||||
"irc": "ircs://irc.hackint.org:6697/#ccchh",
|
||||
"mastodon": "@ccchh@chaos.social",
|
||||
"email": "mail@hamburg.ccc.de",
|
||||
"ml": "talk@hamburg.ccc.de",
|
||||
"matrix": "#ccchh:hamburg.ccc.de"
|
||||
},
|
||||
"feeds": {
|
||||
"blog": {
|
||||
"type": "application/rss+xml",
|
||||
"url": "https://hamburg.ccc.de/feed.xml"
|
||||
},
|
||||
"calendar": {
|
||||
"type": "ical",
|
||||
"url": "webcal://cloud.hamburg.ccc.de/remote.php/dav/public-calendars/QJAdExziSnNJEz5g/?export"
|
||||
}
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Wiki",
|
||||
"url": "https://wiki.hamburg.ccc.de"
|
||||
},
|
||||
{
|
||||
"name": "Git (Forgejo)",
|
||||
"url": "https://git.hamburg.ccc.de"
|
||||
}
|
||||
]
|
||||
}
|
||||
"credentials": {
|
||||
"club-assistant": {
|
||||
"username": "club-assistant",
|
||||
"password": "clubmiau"
|
||||
},
|
||||
"dooris-hauptraum": {
|
||||
"username": "dooris-hauptraum",
|
||||
"password": "doorimiau"
|
||||
}
|
||||
},
|
||||
"dynamic": {
|
||||
"sensors": {
|
||||
"temperature": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "°C",
|
||||
"location": "Hauptraum",
|
||||
"name": "Kueche",
|
||||
"description": "Sensor im Ofen"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "°C",
|
||||
"location": "Hauptraum",
|
||||
"description": "Sensor im Hauptraum"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
],
|
||||
"humidity": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "%",
|
||||
"location": "Hauptraum",
|
||||
"name": "Kueche",
|
||||
"description": "Sensor im Wasserhahn"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
],
|
||||
"beverage_supply": [
|
||||
{
|
||||
"sensor_data": {
|
||||
"unit": "btl"
|
||||
},
|
||||
"allowed_credentials": [
|
||||
"club-assistant"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"state": {
|
||||
"open": {
|
||||
"allowed_credentials": [
|
||||
"dooris-hauptraum"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"api_compatibility": [
|
||||
"14",
|
||||
"15"
|
||||
],
|
||||
"space": "CCCHH",
|
||||
"logo": "https://hamburg.ccc.de/images/logo.svg",
|
||||
"ext_ccc": "erfa",
|
||||
"url": "https://hamburg.ccc.de/",
|
||||
"location": {
|
||||
"address": "Zeiseweg 9, 22765 Hamburg, Germany",
|
||||
"lon": 9.94444,
|
||||
"lat": 53.5584
|
||||
},
|
||||
"contact": {
|
||||
"phone": "+49 40 23830150",
|
||||
"irc": "ircs://irc.hackint.org:6697/#ccchh",
|
||||
"mastodon": "@ccchh@chaos.social",
|
||||
"email": "mail@hamburg.ccc.de",
|
||||
"ml": "talk@hamburg.ccc.de",
|
||||
"matrix": "#ccchh:hamburg.ccc.de"
|
||||
},
|
||||
"feeds": {
|
||||
"blog": {
|
||||
"type": "application/rss+xml",
|
||||
"url": "https://hamburg.ccc.de/feed.xml"
|
||||
},
|
||||
"calendar": {
|
||||
"type": "ical",
|
||||
"url": "webcal://cloud.hamburg.ccc.de/remote.php/dav/public-calendars/QJAdExziSnNJEz5g/?export"
|
||||
}
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Wiki",
|
||||
"url": "https://wiki.hamburg.ccc.de"
|
||||
},
|
||||
{
|
||||
"name": "Git (Forgejo)",
|
||||
"url": "https://git.hamburg.ccc.de"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func getConfigPaths() (paths pathsT) {
|
|||
|
||||
// If paths is still empty we are missing something
|
||||
if len(paths) == 0 {
|
||||
log.Fatalln("Error: Neither env: ", envConfigPath, "nor cli flag was specified, unable to start without config.")
|
||||
log.Fatalln("Error: Neither env:", envConfigPath, "nor cli flag was specified, unable to start without config.")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ type SpaceapidConfig struct {
|
|||
// The dynamic part of the spaceapi JSON
|
||||
Dynamic DynamicStateConfig `json:"dynamic"`
|
||||
// The static part of the spaceapi JSON
|
||||
Response types.SpaceAPIResponseV14 `json:"response"`
|
||||
Response types.SpaceAPIResponse `json:"response"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"git.hamburg.ccc.de/ccchh/spaceapid/types"
|
||||
)
|
||||
|
||||
func Root(resp *types.SpaceAPIResponseV14) func(http.ResponseWriter, *http.Request) {
|
||||
func Root(resp *types.SpaceAPIResponse) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Check if GET method
|
||||
if r.Method != http.MethodGet {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
func StateOpen(
|
||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||
resp *types.SpaceState,
|
||||
resp *types.SpaceAPIState,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||
|
|
@ -37,7 +37,7 @@ func StateOpen(
|
|||
|
||||
func StateMessagePUT(
|
||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||
resp *types.SpaceState,
|
||||
resp *types.SpaceAPIState,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||
|
|
@ -54,7 +54,7 @@ func StateMessagePUT(
|
|||
|
||||
func StateMessageDELETE(
|
||||
authDB config.HTTPBACredentials, validCredentials []config.HTTPBACredentialID,
|
||||
resp *types.SpaceState,
|
||||
resp *types.SpaceAPIState,
|
||||
) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := updateEndpointValidator(authDB, validCredentials, w, r)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func updateEndpointValidator(
|
|||
// Check BasicAuth credentials
|
||||
username, password, ok := r.BasicAuth()
|
||||
if !ok || !util.CheckCredentials(authDB, validCredentials, username, password) {
|
||||
w.Header()["WWW-Authenticate"] = []string{"Basic realm=\"spaceapid\""}
|
||||
w.Header().Set("WWW-Authenticate", "Basic realm=\"spaceapid\"")
|
||||
http.Error(w, "", http.StatusUnauthorized)
|
||||
return []byte{}, errors.New(fmt.Sprintf("Unauthorized request from %s Username: %s Password: %s", r.RemoteAddr, username, password))
|
||||
}
|
||||
|
|
|
|||
2
main.go
2
main.go
|
|
@ -43,7 +43,7 @@ func main() {
|
|||
// Register signal handler
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func(resp *types.SpaceAPIResponseV14) {
|
||||
go func(resp *types.SpaceAPIResponse) {
|
||||
<-sc
|
||||
log.Println("Saving state and shutting down...")
|
||||
persistence.SaveCurrentState(*resp)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ const (
|
|||
|
||||
// MergeOldState merges a given SpaceAPIResponse with the state saved at the time of last program exit and then deletes
|
||||
// the file containing the old state.
|
||||
func MergeOldState(response *types.SpaceAPIResponseV14) {
|
||||
func MergeOldState(response *types.SpaceAPIResponse) {
|
||||
var (
|
||||
err error
|
||||
oldState []byte
|
||||
persistedState types.PersistentStateV14
|
||||
persistedState types.PersistentSpaceState
|
||||
)
|
||||
|
||||
log.Println("Merging old state from", persistentStatePath, "...")
|
||||
|
|
@ -48,7 +48,7 @@ func MergeOldState(response *types.SpaceAPIResponseV14) {
|
|||
}
|
||||
|
||||
// Merge state
|
||||
response.State = persistedState.State
|
||||
response.State.FromPersistentSpaceState(persistedState)
|
||||
|
||||
// Merge sensors
|
||||
for key, environmentSensors := range persistedState.Sensors {
|
||||
|
|
@ -72,7 +72,7 @@ removeOld:
|
|||
}
|
||||
}
|
||||
|
||||
func SaveCurrentState(response types.SpaceAPIResponseV14) {
|
||||
func SaveCurrentState(response types.SpaceAPIResponse) {
|
||||
// Create state directory if not present
|
||||
err := os.MkdirAll(persistentStateDir, 0750)
|
||||
if err != nil {
|
||||
|
|
@ -87,7 +87,7 @@ func SaveCurrentState(response types.SpaceAPIResponseV14) {
|
|||
defer file.Close()
|
||||
|
||||
// Create persistent state
|
||||
persistentStateV14 := types.PersistentStateV14{
|
||||
persistentStateV14 := types.PersistentSpaceState{
|
||||
State: struct {
|
||||
Open bool `json:"open"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
|
|
|
|||
69
types/v14.go
69
types/v14.go
|
|
@ -1,69 +0,0 @@
|
|||
package types
|
||||
|
||||
type SpaceAPIResponseV14 struct {
|
||||
APICompatibility []string `json:"api_compatibility"`
|
||||
Space string `json:"space"`
|
||||
Logo string `json:"logo"`
|
||||
ExtCCC string `json:"ext_ccc"`
|
||||
URL string `json:"url"`
|
||||
Location struct {
|
||||
Address string `json:"address"`
|
||||
Lat float64 `json:"lat"`
|
||||
Lon float64 `json:"lon"`
|
||||
} `json:"location"`
|
||||
State SpaceState `json:"state"`
|
||||
Contact struct {
|
||||
Phone string `json:"phone"`
|
||||
IRC string `json:"irc"`
|
||||
Mastodon string `json:"mastodon"`
|
||||
Email string `json:"email"`
|
||||
ML string `json:"ml"`
|
||||
Matrix string `json:"matrix"`
|
||||
} `json:"contact"`
|
||||
Sensors map[string][]EnvironmentSensor `json:"sensors"`
|
||||
Feeds struct {
|
||||
Blog struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
} `json:"blog"`
|
||||
Calendar struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
} `json:"calendar"`
|
||||
} `json:"feeds"`
|
||||
Links []struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
} `json:"links"`
|
||||
}
|
||||
|
||||
type SpaceState struct {
|
||||
Open bool `json:"open"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type EnvironmentSensor struct {
|
||||
Value float64 `json:"value"`
|
||||
Unit string `json:"unit"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
LastChange int64 `json:"lastchange,omitempty"`
|
||||
}
|
||||
|
||||
type PersistentStateV14 struct {
|
||||
State struct {
|
||||
Open bool `json:"open"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
Message string `json:"message,omitempty"`
|
||||
} `json:"state"`
|
||||
Sensors map[string][]PersistentEnvironmentSensor `json:"sensors,omitempty"`
|
||||
}
|
||||
|
||||
type PersistentEnvironmentSensor struct {
|
||||
Value float64 `json:"value"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
}
|
||||
159
types/v15.go
Normal file
159
types/v15.go
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
package types
|
||||
|
||||
type SpaceAPIResponse struct {
|
||||
APICompatibility []string `json:"api_compatibility"` // REQUIRED
|
||||
Space string `json:"space"` // REQUIRED
|
||||
Logo string `json:"logo"` // REQUIRED
|
||||
URL string `json:"url"` // REQUIRED
|
||||
|
||||
// Minimum number of properties: 1
|
||||
Location struct {
|
||||
Address string `json:"address,omitzero"`
|
||||
Lat float64 `json:"lat,omitzero"`
|
||||
Lon float64 `json:"lon,omitzero"`
|
||||
Timezone string `json:"timezone,omitzero"`
|
||||
CountryCode string `json:"country_code,omitzero"`
|
||||
Hint string `json:"hint,omitzero"`
|
||||
// Minimum number of items: 1
|
||||
Areas []SpaceAPILocationAreas `json:"areas,omitempty"`
|
||||
} `json:"location,omitzero"`
|
||||
|
||||
SpaceFed struct {
|
||||
SpaceNet bool `json:"spacenet,omitzero"`
|
||||
SpaceSAML bool `json:"spacesaml,omitzero"`
|
||||
} `json:"spacefed,omitzero"`
|
||||
|
||||
Cam []string `json:"cam,omitempty"`
|
||||
|
||||
State SpaceAPIState `json:"state,omitzero"`
|
||||
|
||||
Events []SpaceAPIEvents `json:"events,omitempty"`
|
||||
|
||||
Contact struct {
|
||||
Phone string `json:"phone,omitzero"`
|
||||
Sip string `json:"sip,omitzero"`
|
||||
// keymasters
|
||||
Keymasters []struct {
|
||||
Name string `json:"name,omitzero"`
|
||||
IRCNick string `json:"irc_nick,omitzero"`
|
||||
Phone string `json:"phone,omitzero"`
|
||||
Email string `json:"email,omitzero"`
|
||||
Twitter string `json:"twitter,omitzero"`
|
||||
Xmpp string `json:"xmpp,omitzero"`
|
||||
Mastodon string `json:"mastodon,omitzero"`
|
||||
Matrix string `json:"matrix,omitzero"`
|
||||
} `json:"keymasters,omitempty"`
|
||||
IRC string `json:"irc,omitzero"`
|
||||
Twitter string `json:"twitter,omitzero"`
|
||||
Mastodon string `json:"mastodon,omitzero"`
|
||||
Facebook string `json:"facebook,omitzero"`
|
||||
Identica string `json:"identica,omitzero"`
|
||||
Foursquare string `json:"foursquare,omitzero"`
|
||||
Email string `json:"email,omitzero"`
|
||||
ML string `json:"ml,omitzero"`
|
||||
XMPP string `json:"xmpp,omitzero"`
|
||||
IssueMail string `json:"issue_mail,omitzero"`
|
||||
Gopher string `json:"gopher,omitzero"`
|
||||
Matrix string `json:"matrix,omitzero"`
|
||||
Mumble string `json:"mumble,omitzero"`
|
||||
} `json:"contact"`
|
||||
|
||||
Sensors map[string][]EnvironmentSensor `json:"sensors,omitempty"`
|
||||
|
||||
Feeds struct {
|
||||
Blog struct {
|
||||
Type string `json:"type,omitzero"`
|
||||
URL string `json:"url"` // REQUIRED
|
||||
} `json:"blog,omitzero"`
|
||||
Wiki struct {
|
||||
Type string `json:"type,omitzero"`
|
||||
URL string `json:"url"` // REQUIRED
|
||||
} `json:"wiki,omitzero"`
|
||||
Calendar struct {
|
||||
Type string `json:"type,omitzero"`
|
||||
URL string `json:"url"` // REQUIRED
|
||||
} `json:"calendar,omitzero"`
|
||||
Flickr struct {
|
||||
Type string `json:"type,omitzero"`
|
||||
URL string `json:"url"` // REQUIRED
|
||||
} `json:"flickr,omitzero"`
|
||||
} `json:"feeds,omitzero"`
|
||||
|
||||
Projects []string `json:"projects,omitempty"`
|
||||
|
||||
Links []struct {
|
||||
Name string `json:"name"` // REQUIRED
|
||||
URL string `json:"url"` // REQUIRED
|
||||
Description string `json:"description,omitzero"`
|
||||
} `json:"links,omitempty"`
|
||||
|
||||
MembershipPlans []struct {
|
||||
Name string `json:"name"` // REQUIRED
|
||||
Value int64 `json:"value"` // REQUIRED
|
||||
Currency string `json:"currency"` // REQUIRED
|
||||
BillingInterval string `json:"billing_interval"` // REQUIRED
|
||||
Description string `json:"description,omitzero"`
|
||||
} `json:"membership_plans,omitempty"`
|
||||
|
||||
LinkedSpaces []struct {
|
||||
Endpoint string `json:"endpoint,omitzero"`
|
||||
Website string `json:"website,omitzero"`
|
||||
} `json:"linked_spaces,omitempty"`
|
||||
|
||||
ExtCCC string `json:"ext_ccc,omitzero"`
|
||||
}
|
||||
|
||||
type SpaceAPILocationAreas struct {
|
||||
Name string `json:"name,omitzero"`
|
||||
Description string `json:"description,omitzero"`
|
||||
SquareMeters float64 `json:"square_meters"` // REQUIRED
|
||||
}
|
||||
|
||||
type SpaceAPIState struct {
|
||||
Open bool `json:"open,omitempty"`
|
||||
LastChange int64 `json:"lastchange,omitempty"`
|
||||
TriggerPerson string `json:"trigger_person,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Icon struct {
|
||||
Open string `json:"open,omitempty"` // REQUIRED
|
||||
Closed string `json:"closed,omitempty"` // REQUIRED
|
||||
} `json:"icon,omitzero"`
|
||||
}
|
||||
|
||||
func (s *SpaceAPIState) FromPersistentSpaceState(state PersistentSpaceState) {
|
||||
s.Open = state.State.Open
|
||||
s.LastChange = state.State.LastChange
|
||||
s.Message = state.State.Message
|
||||
}
|
||||
|
||||
type SpaceAPIEvents struct {
|
||||
Name string `json:"name"` // REQUIRED
|
||||
Type string `json:"type"` // REQUIRED
|
||||
Timestamp int64 `json:"timestamp"` // REQUIRED
|
||||
Extra string `json:"extra,omitzero"`
|
||||
}
|
||||
|
||||
type EnvironmentSensor struct {
|
||||
Value float64 `json:"value"`
|
||||
Unit string `json:"unit"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
LastChange int64 `json:"lastchange,omitempty"`
|
||||
}
|
||||
|
||||
type PersistentSpaceState struct {
|
||||
State struct {
|
||||
Open bool `json:"open"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
Message string `json:"message,omitempty"`
|
||||
} `json:"state"`
|
||||
Sensors map[string][]PersistentEnvironmentSensor `json:"sensors,omitempty"`
|
||||
}
|
||||
|
||||
type PersistentEnvironmentSensor struct {
|
||||
Value float64 `json:"value"`
|
||||
Location string `json:"location,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
LastChange int64 `json:"lastchange"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue