Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 317dd9aedf | |||
| 7f22302859 | |||
| dc0ae8eb96 | |||
| b07a114227 | |||
| 88f77edadd | |||
| decad4cc82 |
@@ -13,7 +13,7 @@ Just drop the binary on a server and start triaging.
|
|||||||
|
|
||||||
### Option A: Download the Binary
|
### Option A: Download the Binary
|
||||||
|
|
||||||
1. Go to the [Releases](https://epigas.gitea.cloud/RiskRancher/core/releases) tab and download the compiled executable for your OS (Windows/macOS/Linux).
|
1. Go to the [Releases](https://code.riskrancher.com/RiskRancher/core/releases) tab and download the compiled executable for your OS (Windows/macOS/Linux).
|
||||||
2. Place the binary in a dedicated directory and execute it.
|
2. Place the binary in a dedicated directory and execute it.
|
||||||
3. Visit `http://localhost:8080` in your browser.
|
3. Visit `http://localhost:8080` in your browser.
|
||||||
|
|
||||||
@@ -22,8 +22,12 @@ Just drop the binary on a server and start triaging.
|
|||||||
Ensure you have **Go 1.26+** installed (*CGO is required for the native `mattn/go-sqlite3` driver*).
|
Ensure you have **Go 1.26+** installed (*CGO is required for the native `mattn/go-sqlite3` driver*).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://epigas.gitea.cloud/RiskRancher/core
|
git clone https://code.riskrancher.com/RiskRancher/core
|
||||||
cd core
|
cd core
|
||||||
go build -o rr ./cmd/rr/main.go
|
go build -o rr ./cmd/rr/main.go
|
||||||
./rr
|
./rr
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache License 2.0
|
||||||
+3
-3
@@ -4,9 +4,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/server"
|
"code.riskrancher.com/RiskRancher/core/pkg/server"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/ui"
|
"code.riskrancher.com/RiskRancher/core/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
"code.riskrancher.com/RiskRancher/core/pkg/auth"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module epigas.gitea.cloud/RiskRancher/core
|
module code.riskrancher.com/RiskRancher/core
|
||||||
|
|
||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) HandleGetAdapters(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) HandleGetAdapters(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestAdapters(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestAdapters(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
"code.riskrancher.com/RiskRancher/core/pkg/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PasswordResetRequest is the expected JSON payload
|
// PasswordResetRequest is the expected JSON payload
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetGlobalConfig(t *testing.T) {
|
func TestGetGlobalConfig(t *testing.T) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExportSystemState(t *testing.T) {
|
func TestExportSystemState(t *testing.T) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler encapsulates all Admin and Sheriff HTTP logic
|
// Handler encapsulates all Admin and Sheriff HTTP logic
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setupTestAdmin returns the clean Admin Handler and the raw DB
|
// setupTestAdmin returns the clean Admin Handler and the raw DB
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestAnalytics(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestAnalytics(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package analytics
|
package analytics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestAuth(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestAuth(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNotFound is a standard error we can use across our handlers
|
// ErrNotFound is a standard error we can use across our handlers
|
||||||
|
|||||||
+10
-3
@@ -6,9 +6,11 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,9 +20,14 @@ var schemaSQL string
|
|||||||
//go:embed defaults/*.json
|
//go:embed defaults/*.json
|
||||||
var defaultAdaptersFS embed.FS
|
var defaultAdaptersFS embed.FS
|
||||||
|
|
||||||
func InitDB(filepath string) *sql.DB {
|
func InitDB(dbPath string) *sql.DB {
|
||||||
|
|
||||||
dsn := "file:" + filepath + "?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)&_pragma=synchronous(NORMAL)&_pragma=foreign_keys(1)"
|
dir := filepath.Dir(dbPath)
|
||||||
|
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
log.Fatalf("Failed to create database directory: %v", err)
|
||||||
|
}
|
||||||
|
dsn := "file:" + dbPath + "?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)&_pragma=synchronous(NORMAL)&_pragma=foreign_keys(1)"
|
||||||
|
|
||||||
db, err := sql.Open("sqlite", dsn)
|
db, err := sql.Open("sqlite", dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
_ "modernc.org/sqlite" // We need the SQLite driver for the test
|
_ "modernc.org/sqlite" // We need the SQLite driver for the test
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,13 @@ CREATE TABLE IF NOT EXISTS sla_policies (
|
|||||||
);
|
);
|
||||||
|
|
||||||
INSERT OR IGNORE INTO sla_policies (domain, severity, days_to_triage, days_to_remediate, max_extensions) VALUES
|
INSERT OR IGNORE INTO sla_policies (domain, severity, days_to_triage, days_to_remediate, max_extensions) VALUES
|
||||||
('Vulnerability', 'Critical', 3, 14, 1), ('Vulnerability', 'High', 3, 30, 2),
|
('Vulnerability', 'Critical', 3, 14, 1),
|
||||||
('Privacy', 'Critical', 3, 3, 0), ('Privacy', 'High', 3, 7, 1),
|
('Vulnerability', 'High', 3, 30, 2),
|
||||||
|
('Vulnerability', 'Medium', 7, 60, 2),
|
||||||
|
('Vulnerability', 'Low', 14, 90, 3),
|
||||||
|
('Vulnerability', 'Info', 30, 180, 5),
|
||||||
|
('Privacy', 'Critical', 3, 3, 0),
|
||||||
|
('Privacy', 'High', 3, 7, 1),
|
||||||
('Incident', 'Critical', 3, 1, 0);
|
('Incident', 'Critical', 3, 1, 0);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package datastore
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SQLiteStore struct {
|
type SQLiteStore struct {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLiteStore) UpdateAppConfig(ctx context.Context, config domain2.AppConfig) error {
|
func (s *SQLiteStore) UpdateAppConfig(ctx context.Context, config domain2.AppConfig) error {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLiteStore) GetSheriffAnalytics(ctx context.Context) (domain2.SheriffAnalytics, error) {
|
func (s *SQLiteStore) GetSheriffAnalytics(ctx context.Context) (domain2.SheriffAnalytics, error) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLiteStore) SaveDraft(ctx context.Context, d domain2.DraftTicket) error {
|
func (s *SQLiteStore) SaveDraft(ctx context.Context, d domain2.DraftTicket) error {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLiteStore) IngestTickets(ctx context.Context, tickets []domain2.Ticket) error {
|
func (s *SQLiteStore) IngestTickets(ctx context.Context, tickets []domain2.Ticket) error {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SQLiteStore) GetTickets(ctx context.Context) ([]domain.Ticket, error) {
|
func (s *SQLiteStore) GetTickets(ctx context.Context) ([]domain.Ticket, error) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package ingest
|
package ingest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) HandleIngest(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) HandleIngest(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestIngest(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestIngest(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
"code.riskrancher.com/RiskRancher/core/pkg/auth"
|
||||||
domain2 "epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
domain2 "code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) HandleSaveDraft(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) HandleSaveDraft(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package report
|
package report
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestReport(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestReport(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@ package server
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/sla"
|
"code.riskrancher.com/RiskRancher/core/pkg/sla"
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package server
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/adapters"
|
"code.riskrancher.com/RiskRancher/core/pkg/adapters"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/admin"
|
"code.riskrancher.com/RiskRancher/core/pkg/admin"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/analytics"
|
"code.riskrancher.com/RiskRancher/core/pkg/analytics"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
"code.riskrancher.com/RiskRancher/core/pkg/auth"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/ingest"
|
"code.riskrancher.com/RiskRancher/core/pkg/ingest"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/report"
|
"code.riskrancher.com/RiskRancher/core/pkg/report"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/tickets"
|
"code.riskrancher.com/RiskRancher/core/pkg/tickets"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/ui"
|
"code.riskrancher.com/RiskRancher/core/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterRoutes(app *App) {
|
func RegisterRoutes(app *App) {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultSLACalculator implements the SLACalculator interface
|
// DefaultSLACalculator implements the SLACalculator interface
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package tickets
|
package tickets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler encapsulates all Ticket-related HTTP logic
|
// Handler encapsulates all Ticket-related HTTP logic
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/datastore"
|
"code.riskrancher.com/RiskRancher/core/pkg/datastore"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestTickets(t *testing.T) (*Handler, *sql.DB) {
|
func setupTestTickets(t *testing.T) (*Handler, *sql.DB) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InlineUpdateRequest struct {
|
type InlineUpdateRequest struct {
|
||||||
|
|||||||
@@ -10,15 +10,18 @@
|
|||||||
<div class="tab-nav">
|
<div class="tab-nav">
|
||||||
<button class="tab-btn active" onclick="switchTab('tab-metrics', this)">📊 Metrics</button>
|
<button class="tab-btn active" onclick="switchTab('tab-metrics', this)">📊 Metrics</button>
|
||||||
<button class="tab-btn" onclick="switchTab('tab-performance', this)">📡 Performance</button>
|
<button class="tab-btn" onclick="switchTab('tab-performance', this)">📡 Performance</button>
|
||||||
|
{{ block "pro_risk_tab_btn" .}}
|
||||||
<button class="tab-btn" style="color: #94a3b8; cursor: not-allowed;" title="Available in RiskRancher Pro">
|
<button class="tab-btn" style="color: #94a3b8; cursor: not-allowed;" title="Available in RiskRancher Pro">
|
||||||
🔒 Risk Reviews (Pro)
|
🔒 Risk Reviews (Pro)
|
||||||
</button>
|
</button>
|
||||||
|
{{ end }}
|
||||||
<button class="tab-btn" onclick="switchTab('tab-config', this)">⚙️ Configuration</button>
|
<button class="tab-btn" onclick="switchTab('tab-config', this)">⚙️ Configuration</button>
|
||||||
<button class="tab-btn" onclick="switchTab('tab-feed', this)">📻 System Logs</button>
|
<button class="tab-btn" onclick="switchTab('tab-feed', this)">📻 System Logs</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "admin_metrics" .}}
|
{{template "admin_metrics" .}}
|
||||||
{{template "admin_performance" .}}
|
{{template "admin_performance" .}}
|
||||||
|
{{block "pro_risk_tab_content" .}}{{end}}
|
||||||
{{template "admin_config" .}}
|
{{template "admin_config" .}}
|
||||||
{{template "admin_feed" .}}
|
{{template "admin_feed" .}}
|
||||||
{{template "admin_modals" .}}
|
{{template "admin_modals" .}}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px;">
|
{{block "pro_source_routing" .}}
|
||||||
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; background: #f8fafc;">
|
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; background: #f8fafc;">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
||||||
<h3 style="margin: 0; color: #64748b;">🛤️ Source Routing</h3>
|
<h3 style="margin: 0; color: #64748b;">🛤️ Source Routing</h3>
|
||||||
@@ -35,11 +35,12 @@
|
|||||||
<a href="https://RiskRancher.com/pro" target="_blank" style="color: #8b5cf6; text-decoration: none; font-weight: bold; font-size: 0.85rem;">Learn about RiskRancher Pro →</a>
|
<a href="https://RiskRancher.com/pro" target="_blank" style="color: #8b5cf6; text-decoration: none; font-weight: bold; font-size: 0.85rem;">Learn about RiskRancher Pro →</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 20px;">
|
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 20px;">
|
||||||
|
|
||||||
|
{{block "pro_sla_policy" .}}
|
||||||
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; position: relative;">
|
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; position: relative;">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
||||||
<div>
|
<div>
|
||||||
@@ -76,24 +77,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; display: flex; flex-direction: column;">
|
<div style="border: 1px solid #e2e8f0; border-radius: 8px; padding: 15px; display: flex; flex-direction: column;">
|
||||||
<h3 style="margin: 0 0 15px 0;">⚙️ Operations</h3>
|
<h3 style="margin: 0 0 15px 0;">⚙️ Operations</h3>
|
||||||
|
|
||||||
<div style="margin-bottom: 20px;">
|
{{block "pro_backups" .}}
|
||||||
<label style="font-weight: bold; display: flex; justify-content: space-between;">
|
{{end}}
|
||||||
Automated Backups
|
|
||||||
<span style="font-size: 0.75rem; color: #8b5cf6; font-weight: normal;">Pro Feature</span>
|
|
||||||
</label>
|
|
||||||
<div style="display: flex; gap: 10px; margin-top: 5px;">
|
|
||||||
<select disabled style="flex: 1; padding: 6px; background: #f1f5f9; color: #94a3b8; cursor: not-allowed; border: 1px solid #cbd5e1;">
|
|
||||||
<option>Manual Only (Free Core)</option>
|
|
||||||
<option>Daily Automated</option>
|
|
||||||
<option>Weekly Automated</option>
|
|
||||||
</select>
|
|
||||||
<button class="btn btn-secondary" style="color: #94a3b8; border-color: #cbd5e1;" onclick="showUpsell('Automated DB Backups')">🔒 Apply</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 20px;">
|
<div style="margin-bottom: 20px;">
|
||||||
<label style="font-weight: bold;">Data Portability</label>
|
<label style="font-weight: bold;">Data Portability</label>
|
||||||
|
|||||||
@@ -8,9 +8,11 @@
|
|||||||
</a>
|
</a>
|
||||||
<a href="/dashboard?tab=chute" class="tab-btn {{if eq .CurrentTab "chute"}}active{{end}}">🤠 The Chute (Assigned)</a>
|
<a href="/dashboard?tab=chute" class="tab-btn {{if eq .CurrentTab "chute"}}active{{end}}">🤠 The Chute (Assigned)</a>
|
||||||
|
|
||||||
|
{{block "pro_verification_tab" .}}
|
||||||
<a href="javascript:void(0)" onclick="showUpsell('E2E Exception & Verification Pipeline')" class="tab-btn" style="color: #94a3b8;">
|
<a href="javascript:void(0)" onclick="showUpsell('E2E Exception & Verification Pipeline')" class="tab-btn" style="color: #94a3b8;">
|
||||||
🔒 Pending Verification (Pro)
|
🔒 Pending Verification (Pro)
|
||||||
</a>
|
</a>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<a href="/dashboard?tab=archives" class="tab-btn {{if eq .CurrentTab "archives"}}active{{end}}">
|
<a href="/dashboard?tab=archives" class="tab-btn {{if eq .CurrentTab "archives"}}active{{end}}">
|
||||||
🗄️ The Archives
|
🗄️ The Archives
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.CurrentTab = "{{.CurrentTab}}";
|
window.CurrentTab = "{{.CurrentTab}}";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{template "dash_tabs" .}}
|
{{template "dash_tabs" .}}
|
||||||
|
|
||||||
|
{{block "pro_risk_tab_content" .}}{{end}}
|
||||||
|
|
||||||
<div class="tab-pane active">
|
<div class="tab-pane active">
|
||||||
{{template "dash_table" .}}
|
{{template "dash_table" .}}
|
||||||
</div>
|
</div>
|
||||||
@@ -13,5 +14,4 @@
|
|||||||
{{template "dash_modals" .}}
|
{{template "dash_modals" .}}
|
||||||
|
|
||||||
<script src="/static/dashboard.js"></script>
|
<script src="/static/dashboard.js"></script>
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -13,9 +13,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
"code.riskrancher.com/RiskRancher/core/pkg/auth"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/domain"
|
"code.riskrancher.com/RiskRancher/core/pkg/domain"
|
||||||
"epigas.gitea.cloud/RiskRancher/core/pkg/report"
|
"code.riskrancher.com/RiskRancher/core/pkg/report"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed templates/* templates/components/* static/*
|
//go:embed templates/* templates/components/* static/*
|
||||||
|
|||||||
Reference in New Issue
Block a user