merge eva repos into single repository

This commit is contained in:
gidsi 2018-04-20 18:08:55 +02:00
commit 200dd620ae
52 changed files with 2281 additions and 0 deletions

14
LICENSE.md Normal file
View file

@ -0,0 +1,14 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

2
backend/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
eva-backend
.idea

15
backend/Dockerfile Normal file
View file

@ -0,0 +1,15 @@
FROM golang:alpine as builder
RUN apk --no-cache add git
WORKDIR /go/src/app
COPY . .
RUN go get -d -v ./...
RUN go install -v ./...
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /go/bin/app .
COPY config.yaml config.yaml
EXPOSE 8080
CMD ["./app", "-shared_secret=$SHARED_SECRET"]

15
backend/README.md Normal file
View file

@ -0,0 +1,15 @@
eva-backend
===========
See yaml file for database config
```bash
go get
go install
SHARED_SECRET=foo eva-backend
```
SpaceAPI extensions
===================
* Key `ext_ccc` describes Chaos Computer Club relation status (Example values: `"chaostreff"` or `"erfa"`)

47
backend/calendar.go Normal file
View file

@ -0,0 +1,47 @@
package main
import (
"github.com/gidsi/ics-golang"
"log"
)
func getCalendars() {
spaceDataArray := readSpacedata()
for _, spaceData := range spaceDataArray {
parser := ics.New()
parserChan := parser.GetInputChan()
parserChan <- spaceData.Feeds.Calendar.Url
outputChan := parser.GetOutputChan()
calendar := Calendar{}
calendar.Space = spaceData.Space
events := []Event{}
go func() {
for event := range outputChan {
events = append(events, mapEventObject(event))
}
}()
parser.Wait()
calendar.Events = events
writeCalendar(calendar)
log.Println("calendar write done for " + spaceData.Space)
}
}
func mapEventObject(event *ics.Event) Event {
eventData := Event{}
eventData.Start = event.GetStart()
eventData.ImportedId = event.GetImportedID()
eventData.Status = event.GetStatus()
eventData.Description = event.GetDescription()
eventData.Location = event.GetLocation()
eventData.Summary = event.GetSummary()
eventData.Rrule = event.GetRRule()
eventData.Url = event.GetUrl()
eventData.Class = event.GetClass()
eventData.Sequence = event.GetSequence()
eventData.WholeDayEvent = event.GetWholeDayEvent()
return eventData
}

3
backend/config.yaml Normal file
View file

@ -0,0 +1,3 @@
---
mongodb_server: database
mongodb_database: eva

7
backend/configFile.go Normal file
View file

@ -0,0 +1,7 @@
package main
type ConfigFile struct {
SharedSecret string `yaml:"shared_secret,omitempty"`
MongoDbServer string `yaml:"mongodb_server,omitempty"`
MongoDbDatabase string `yaml:"mongodb_database,omitempty"`
}

115
backend/database.go Normal file
View file

@ -0,0 +1,115 @@
package main
import (
"log"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
func writeSpaceData(data SpaceData) {
if(data.Space != "") {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("spacedata")
_, err = c.Upsert(bson.M{ "space": data.Space }, data)
if err != nil {
log.Fatal(err)
}
}
}
func writeSpaceurl(spaceUrl SpaceUrl) {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("spaceurl")
count, _ := c.Find(bson.M{ "url": spaceUrl.Url }).Count()
if(count == 0) {
c.Insert(spaceUrl);
}
}
func writeCalendar(calendar Calendar) {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("calendar")
c.Upsert(bson.M{ "space": calendar.Space }, calendar)
}
func updateSpaceurl(spaceUrl SpaceUrl) {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("spaceurl")
c.Update(bson.M{ "url": spaceUrl.Url }, spaceUrl);
}
func readSpacedata() []SpaceData {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("spacedata")
result := []SpaceData{}
c.Find(bson.M{}).Iter().All(&result)
return result
}
func readSpaceurl() []SpaceUrl {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("spaceurl")
result := []SpaceUrl{}
c.Find(bson.M{}).Iter().All(&result)
return result
}
func readCalendar() []Calendar {
session, err := mgo.Dial(config.MongoDbServer)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB(config.MongoDbDatabase).C("calendar")
result := []Calendar{}
c.Find(bson.M{}).Iter().All(&result)
return result
}

92
backend/eva-backend.go Normal file
View file

@ -0,0 +1,92 @@
package main
import (
"net/http"
"encoding/json"
"gopkg.in/yaml.v2"
"log"
"io/ioutil"
"os"
"time"
"github.com/gorilla/mux"
)
var config = ConfigFile{}
func main() {
data, _ := ioutil.ReadFile("config.yaml")
yaml.Unmarshal(data, &config)
config.SharedSecret = os.Getenv("SHARED_SECRET")
router := NewRouter()
http.Handle("/", router)
log.Fatal(http.ListenAndServe(":8080", router))
}
func getJson(url string, target interface{}) error {
r, err := http.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
func SpaceDataIndex(w http.ResponseWriter, r *http.Request) {
ReturnJson(w, readSpacedata())
}
func SpaceUrlIndex(w http.ResponseWriter, r *http.Request) {
ReturnJson(w, readSpaceurl())
}
func CalendarIndex(w http.ResponseWriter, r *http.Request) {
ReturnJson(w, readCalendar())
}
func SpaceUrlAdd(w http.ResponseWriter, r *http.Request) {
spaceUrl := SpaceUrl{}
createEntry(&spaceUrl, w, r)
spaceUrl.Validated = false
writeSpaceurl(spaceUrl)
}
func SpaceUrlUpdate(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
SharedSecret := vars["SharedSecret"]
if(SharedSecret == config.SharedSecret) {
spaceUrl := SpaceUrl{}
createEntry(&spaceUrl, w, r)
updateSpaceurl(spaceUrl)
}
}
func loadSpaceData() {
spaceUrls := readSpaceurl()
timestamp := time.Now().Unix()
for _, spaceUrl := range spaceUrls {
if(spaceUrl.Validated && int64(spaceUrl.LastUpdated + 60) < timestamp) {
spaceData := SpaceData{}
err := getJson(spaceUrl.Url, &spaceData)
if(err != nil) {
log.Println(spaceUrl.Url)
log.Println(err)
} else {
writeSpaceData(spaceData)
spaceUrl.LastUpdated = timestamp
updateSpaceurl(spaceUrl)
}
}
}
}
func refreshData(w http.ResponseWriter, r *http.Request) {
loadSpaceData()
getCalendars()
w.WriteHeader(204)
}

23
backend/event.go Normal file
View file

@ -0,0 +1,23 @@
package main
import "time"
type Calendar struct {
Space string
Events []Event
}
type Event struct {
Start time.Time `json:"start"`
ImportedId string `json:"importId"`
Status string `json:"status"`
Description string `json:"description"`
Location string `json:"location"`
Summary string `json:"summary"`
Rrule string `json:"rrule"`
Class string `json:"class"`
Url string `json:"url"`
Sequence int `json:"sequence"`
WholeDayEvent bool `json:"whileDayEvent"`
}

29
backend/logger.go Normal file
View file

@ -0,0 +1,29 @@
package main
import (
"log"
"net/http"
"time"
)
func Logger(inner http.Handler, name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
inner.ServeHTTP(w, r)
log.Printf(
"%s\t%s\t%s\t%s",
r.Method,
r.RequestURI,
name,
time.Since(start),
)
})
}
func logError(err error) {
if err != nil {
log.Fatal(err)
}
}

48
backend/response.go Normal file
View file

@ -0,0 +1,48 @@
package main
import (
"net/http"
"encoding/json"
"fmt"
)
type DataObject interface {
Save() DataObject
}
func Index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello? Yes, this is dog!")
}
func ReturnJson(w http.ResponseWriter, v interface{}) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "content-type")
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(v); err != nil {
panic(err)
}
}
func ReturnDataNotFound(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound)
}
func createEntry(i interface{}, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "content-type")
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if err := json.NewDecoder(r.Body).Decode(i); err != nil {
w.WriteHeader(422) // unprocessable entity
if err := json.NewEncoder(w).Encode(err); err != nil {
panic(err)
}
} else {
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(i); err != nil {
panic(err)
}
}
}

51
backend/router.go Normal file
View file

@ -0,0 +1,51 @@
package main
import (
"net/http"
"github.com/gorilla/mux"
"log"
)
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range IndexRoutes {
var handler http.Handler
handler = Logger(route.Handler, route.Name)
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
router.
Methods("OPTIONS").
Name("Options Handler").
Handler(http.HandlerFunc(optionsHandler))
}
router.
Methods("OPTIONS").
Name("Options Handler").
Handler(http.HandlerFunc(optionsHandler))
router.NotFoundHandler = http.HandlerFunc(notFound)
return router
}
func notFound(w http.ResponseWriter, r *http.Request) {
log.Print("---------------------------------")
log.Print(w)
log.Print("---------------------------------")
log.Print(r)
log.Print("---------------------------------")
w.WriteHeader(http.StatusNotFound)
}
func optionsHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE")
w.WriteHeader(200)
}

58
backend/routes.go Normal file
View file

@ -0,0 +1,58 @@
package main
import "net/http"
type Route struct {
Name string
Method string
Pattern string
Handler http.HandlerFunc
}
type Routes []Route
var IndexRoutes = Routes{
Route{
"Index",
"GET",
"/",
Index,
},
Route{
"SpaceDataIndex",
"GET",
"/spaces",
SpaceDataIndex,
},
Route{
"SpaceUrlIndex",
"GET",
"/urls",
SpaceUrlIndex,
},
Route{
"CalendarIndex",
"GET",
"/calendar",
CalendarIndex,
},
Route{
"SpaceUrlAdd",
"POST",
"/urls",
SpaceUrlAdd,
},
Route{
"SpaceUrlUpdate",
"PUT",
"/urls/{SharedSecret}",
SpaceUrlUpdate,
},
Route{
"RefreshData",
"GET",
"/refresh",
refreshData,
},
}

44
backend/spacedata.go Normal file
View file

@ -0,0 +1,44 @@
package main
type Feed struct {
Type string `json:"type"`
Url string `json:"url"`
}
type Location struct {
Address string `json:"address"`
Lon float32 `json:"lon"`
Lat float32 `json:"lat"`
}
type Contact struct {
Twitter string `json:"twitter"`
Phone string `json:"phone"`
Irc string `json:"irc"`
Email string `json:"email"`
Ml string `json:"ml"`
IssueMail string `json:"issue_mail"`
}
type State struct {
Open bool `json:"open"`
}
type Feeds struct {
Blog Feed `json:"blog"`
Wiki Feed `json:"wiki"`
Calendar Feed `json:"calendar"`
}
type SpaceData struct {
Api string `json:"api"`
Space string `json:"space"`
Logo string `json:"logo"`
Url string `json:"url"`
Location Location `json:"location"`
Contact Contact `json:"contact"`
IssueReportChannels []string `json:"issue_report_channels"`
State State `json:"state"`
Feeds Feeds `json:"feeds"`
Ext_ccc string `json:"ext_ccc"`
}

7
backend/spaceurl.go Normal file
View file

@ -0,0 +1,7 @@
package main
type SpaceUrl struct {
Url string `json:"url"`
Validated bool `json:"validated"`
LastUpdated int64 `json:"lastUpdated"`
}

17
docker-compose.yml Normal file
View file

@ -0,0 +1,17 @@
version: "3"
services:
frontend:
build: ./frontend
image: gidsi/spaceapi-ccc-frontend:latest
depends_on:
- backend
backend:
build: ./backend
image: gidsi/spaceapi-ccc-backend:latest
env_file: .env
depends_on:
- database
database:
image: mongo:latest
volumes:
- /opt/eva:/data/db

18
frontend/.gitignore vendored Normal file
View file

@ -0,0 +1,18 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*

11
frontend/.travis.yml Normal file
View file

@ -0,0 +1,11 @@
language: node_js
node_js:
- "5"
cache:
directories:
- node_modules
script:
- npm run deploy

11
frontend/Dockerfile Normal file
View file

@ -0,0 +1,11 @@
FROM node as builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/build/ /usr/share/nginx/html/
RUN mkdir -p /tmp/osm/cache
COPY nginx.conf /etc/nginx/nginx.conf

Some files were not shown because too many files have changed in this diff Show more