diff --git a/internal/darkstorm_backend/README.md b/internal/darkstorm_backend/README.md index 4239662..799c43b 100644 --- a/internal/darkstorm_backend/README.md +++ b/internal/darkstorm_backend/README.md @@ -105,6 +105,8 @@ If an error status code is returned then the body will be as follows. `errorCode`'s returned from the main library: +* misconfigured + * Backend is configured incorrectly (such as App returning nil crash table, but key has crash permission) * invalidKey * API Key is invalid or does not have the needed permission for the request. * invalidBody diff --git a/internal/darkstorm_backend/crash.go b/internal/darkstorm_backend/crash.go index 5a1dade..064ffb3 100644 --- a/internal/darkstorm_backend/crash.go +++ b/internal/darkstorm_backend/crash.go @@ -1,59 +1,77 @@ package darkstorm -import "net/http" +import ( + "encoding/json" + "errors" + "net/http" +) type ArchivedCrash struct { - Error string - Stack string - Platform string + Error string `json:"error" bson:"error"` + Stack string `json:"stack" bson:"stack"` + Platform string `json:"platform" bson:"platform"` } type IndividualCrash struct { - Platform string - Error string - Stack string - Count int + Platform string `json:"platform" bson:"platform"` + Error string `json:"error" bson:"error"` + Stack string `json:"stack" bson:"stack"` + Count int `json:"count" bson:"count"` } type CrashReport struct { - ID string - Error string - FirstLine string - Individual []IndividualCrash + ID string `json:"id" bson:"_id"` + Error string `json:"error" bson:"error"` + FirstLine string `json:"firstLine" bson:"firstLine"` + Individual []IndividualCrash `json:"individual" bson:"individual"` } func (c CrashReport) GetID() string { return c.ID } -type crashReq struct { - ID string - Platform string - Error string - Stack string -} - func (b *Backend) reportCrash(w http.ResponseWriter, r *http.Request) { + var ap App hdr, err := b.ParseHeader(r) - if hdr.k == nil || hdr.k.Perm["crash"] { - w.WriteHeader(http.StatusUnauthorized) + if hdr.k != nil { + ap = b.GetApp(hdr.k) + } + if ap == nil || hdr.k.Perm["crash"] || errors.Is(err, ErrApiKeyUnauthorized) { + ReturnError(w, http.StatusUnauthorized, "invalidKey", "Application not authorized") + return + } else if err != nil { + ReturnError(w, http.StatusInternalServerError, "internal", "Server error") return } - if err != nil { - //TODO + defer r.Body.Close() + var crash IndividualCrash + err = json.NewDecoder(r.Body).Decode(&crash) + if err != nil || crash.Platform == "" || crash.Error == "" || crash.Stack == "" { + ReturnError(w, http.StatusBadRequest, "invalidBody", "Bad request") return } - //TODO + tab := ap.CrashTable() + if tab == nil { + ReturnError(w, http.StatusInternalServerError, "misconfigured", "Server misconfigured") + return + } + if !tab.IsArchived(crash) { + err = tab.InsertCrash(crash) + if err != nil { + ReturnError(w, http.StatusInternalServerError, "internal", "Server error") + return + } + } + w.WriteHeader(http.StatusCreated) } func (b *Backend) deleteCrash(w http.ResponseWriter, r *http.Request) { hdr, err := b.ParseHeader(r) - if hdr.k == nil || hdr.k.Perm["management"] { - w.WriteHeader(http.StatusUnauthorized) + if hdr.k == nil || hdr.k.Perm["management"] || errors.Is(err, ErrApiKeyUnauthorized) { + ReturnError(w, http.StatusUnauthorized, "invalidKey", "Application not authorized") return - } - if err != nil { - //TODO + } else if err != nil { + ReturnError(w, http.StatusInternalServerError, "internal", "Server error") return } //TODO diff --git a/internal/darkstorm_backend/db.go b/internal/darkstorm_backend/db.go index 0a9e9ac..94e17f8 100644 --- a/internal/darkstorm_backend/db.go +++ b/internal/darkstorm_backend/db.go @@ -21,5 +21,11 @@ type Table[T IDStruct] interface { type CrashTable interface { Table[CrashReport] - InsertCrash(ID string, report IndividualCrash) error + // Move a crash type to archive. All instances that perfectly match that appear in CrashReport.Individual should be deleted. + // If a CrashReport ends up with an empty Individual array it should also be deleted. + Archive(ArchivedCrash) + IsArchived(IndividualCrash) bool + // Add the IndividualCrash report to the crash table. If a CrashReport exists that matches, then it gets added to CrashReport.Individual. + // If an IndividualCrash exists that is a perfect match, Count is incremented instead of adding it to the array. + InsertCrash(IndividualCrash) error } diff --git a/internal/darkstorm_backend/user.go b/internal/darkstorm_backend/user.go index 5b5699a..e97345a 100644 --- a/internal/darkstorm_backend/user.go +++ b/internal/darkstorm_backend/user.go @@ -118,6 +118,9 @@ func (b *Backend) CreateUser(w http.ResponseWriter, r *http.Request) { if hdr.k == nil || !hdr.k.Perm["user"] || errors.Is(err, ErrApiKeyUnauthorized) { ReturnError(w, http.StatusUnauthorized, "invalidKey", "Application not authorized") return + } else if err != nil { + ReturnError(w, http.StatusInternalServerError, "internal", "Server error") + return } defer r.Body.Close() var req createUserRequest @@ -186,6 +189,9 @@ func (b *Backend) Login(w http.ResponseWriter, r *http.Request) { if hdr.k == nil || !hdr.k.Perm["user"] || errors.Is(err, ErrApiKeyUnauthorized) { ReturnError(w, http.StatusUnauthorized, "invalidKey", "Application not authorized") return + } else if err != nil { + ReturnError(w, http.StatusInternalServerError, "internal", "Server error") + return } defer r.Body.Close() var req loginRequest