diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3561b5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,35 @@ +# syntax=docker/dockerfile:1 + +FROM golang:1.22.2 + +WORKDIR /app + +COPY go.mod go.sum ./ + +RUN go mod download + +COPY auth ./auth +COPY config ./config +COPY db ./db +COPY docs ./docs +COPY handlers ./handlers +COPY models ./models +COPY services ./services +COPY setup ./setup +COPY utils ./utils +COPY webhooks ./webhooks +COPY data ./data +COPY web-ui ./web-ui +COPY config.yaml key.pem cert.pem main.go rsakey.pem build.sh run.sh ./ + +RUN CGO_ENABLED=1 GOOS=linux go build -o dingus-server + +# Optional: +# To bind to a TCP port, runtime parameters must be supplied to the docker command. +# But we can document in the Dockerfile what ports +# the application is going to listen on by default. +# https://docs.docker.com/reference/dockerfile/#expose +EXPOSE 443 + +# Run +CMD ["/app/run.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 556ba2c..13df6d8 100644 --- a/README.md +++ b/README.md @@ -48,15 +48,28 @@ This project is an RFID access control system's backend server written in Golang - `web-ui`: Frontend assets. ## Getting Started +### Docker +#### Build +`docker-compose build` +#### Run Interactive +`docker-compose up` -### Prerequisites +`ctrl-c` to stop. + +#### Run in background (Detached) +`docker-compose up -d` +#### Stop +`docker-compose down` + +### Native +#### Prerequisites - [Go](https://go.dev/doc/install) (latest stable version) - Access to [Wild Apricot API](https://gethelp.wildapricot.com/en/articles/182-using-wildapricot-s-api) - SSL certificate and key - GCC for SQLite Go package compilation (requires cgo) -### Setting CGO_ENABLED +#### Setting CGO_ENABLED To successfully build and run this project, `CGO_ENABLED` must be set to `1`. This allows for the compilation of C code, a requirement for the SQLite package used in the project. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..dc70b99 --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export WILD_APRICOT_API_KEY=ilyglbbwzai5suuxt4nai0kqx5evvh +export WILD_APRICOT_WEBHOOK_TOKEN=08a7gv08abwDYGd77cxv980asdfy98zxc87 +export WILD_APRICOT_SSO_CLIENT_ID=t8jw60pj3f +export WILD_APRICOT_SSO_CLIENT_SECRET=5k8nct39ootl8wt0gkpxe22v8phi5a +export WILD_APRICOT_SSO_REDIRECT_URI=/replaceme +export LOG_LEVEL=INFO +export COOKIE_STORE_SECRET=cookiestoresecret +export CGO_ENABLED=1 +export GOOS=linux +/usr/local/go/bin/go build -o dingus-server \ No newline at end of file diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..efdce01 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,5 @@ +services: + dingus-server: + build: . + ports: + - "443:443" \ No newline at end of file diff --git a/config.yaml b/config.yaml index 82df99a..cf2874c 100644 --- a/config.yaml +++ b/config.yaml @@ -1,7 +1,7 @@ -cert_file: .ssh/id_rsa/dev_pubkey.pem +cert_file: cert.pem contact_filter_query: "(Status eq Active or Status eq PendingRenewal) and 'Door Key' ne NULL" -database_path: db/data/tagsdb.sqlite -key_file: .ssh/id_rsa/dev_secret.pem +database_path: data/tagsdb.sqlite +key_file: key.pem tag_id_field_name: Door Key training_field_name: Safety Training wild_apricot_account_id: 232582 diff --git a/db/data/.gitignore b/db/data/.gitignore deleted file mode 100644 index c1462eb..0000000 --- a/db/data/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# This file is here in order to commit the empty data folder to the git repo. -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/models/wildApricotContact.go b/models/wildApricotContact.go index ab11857..da26d9c 100644 --- a/models/wildApricotContact.go +++ b/models/wildApricotContact.go @@ -65,10 +65,10 @@ func (c *Contact) ExtractContactData(cfg *config.Config) (int, uint32, []string, trainingLabels, err := c.ExtractTrainingLabels(cfg) if err != nil { - return 0, 0, nil, fmt.Errorf("error extracting training labels for contact %d: %v", c.Id, err) + err = fmt.Errorf("error extracting training labels for contact %d: %v", c.Id, err) } - return c.Id, tagID, trainingLabels, nil + return c.Id, tagID, trainingLabels, err } func parseTagId(fieldValue FieldValue) (uint32, error) { diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..10f461b --- /dev/null +++ b/run.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export WILD_APRICOT_API_KEY=ilyglbbwzai5suuxt4nai0kqx5evvh +export WILD_APRICOT_WEBHOOK_TOKEN=08a7gv08abwDYGd77cxv980asdfy98zxc87 +export WILD_APRICOT_SSO_CLIENT_ID=t8jw60pj3f +export WILD_APRICOT_SSO_CLIENT_SECRET=5k8nct39ootl8wt0gkpxe22v8phi5a +export WILD_APRICOT_SSO_REDIRECT_URI=/replaceme +export LOG_LEVEL=INFO +export COOKIE_STORE_SECRET=cookiestoresecret +export CGO_ENABLED=1 +export GOOS=linux +./dingus-server \ No newline at end of file diff --git a/services/dbService.go b/services/dbService.go index 6842d07..579b4b9 100644 --- a/services/dbService.go +++ b/services/dbService.go @@ -134,7 +134,8 @@ func (s *DBService) ProcessContactsData(contacts []models.Contact) error { for _, contact := range contacts { contactId, tagId, trainingLabels, err := contact.ExtractContactData(s.cfg) if err != nil { - return err + // output the error and save any data that was retrieved. + s.log.Error(err) } if contactId != 0 && tagId != 0 { @@ -167,6 +168,7 @@ func (s *DBService) ProcessContactsData(contacts []models.Contact) error { tx.Rollback() return err } + return tx.Commit() } diff --git a/services/wildApricotService.go b/services/wildApricotService.go index 4f23fe9..fa303d7 100644 --- a/services/wildApricotService.go +++ b/services/wildApricotService.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "rfid-backend/config" @@ -47,7 +46,7 @@ func NewWildApricotService(cfg *config.Config, logger *logrus.Logger) *WildApric func readResponseBody(resp *http.Response) ([]byte, error) { defer resp.Body.Close() - return ioutil.ReadAll(resp.Body) + return io.ReadAll(resp.Body) } func handleHTTPError(resp *http.Response) error { @@ -169,6 +168,7 @@ func (s *WildApricotService) GetContacts() ([]models.Contact, error) { } s.log.Infof("Parsed %d contacts from response", len(contacts)) + return contacts, nil }