Compare commits
5 Commits
be4ed5c497
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4acf4971bf | |||
| d4b7554633 | |||
| 3b1fceb889 | |||
| ac35bcb776 | |||
| e86d87da36 |
21
backend/Makefile
Normal file
21
backend/Makefile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
CODIT_SERVER_NAME=codit-server
|
||||||
|
CODIT_SERVER_VERSION=0.5.0
|
||||||
|
|
||||||
|
CODIT_SERVER_SRCS = cmd/codit-server/main.go
|
||||||
|
CODIT_DATA_BROWSER_SRCS = cmd/codit-data-browser/main.go
|
||||||
|
|
||||||
|
all: codit-server codit-data-browser
|
||||||
|
|
||||||
|
codit-server:
|
||||||
|
CGO_ENABLED=0 go build -x -ldflags "-X 'main.CODIT_SERVER_NAME=$(NAME)' -X 'main.CODIT_SERVER_VERSION=$(VERSION)'" -o $@ $(CODIT_SERVER_SRCS)
|
||||||
|
|
||||||
|
codit-server.debug:
|
||||||
|
CGO_ENABLED=1 go build -race -x -ldflags "-X 'main.CODIT_SERVER_NAME=$(NAME)' -X 'main.CODIT_SERVER_VERSION=$(VERSION)'" -o $@ $(CODIT_SERVER_SRCS)
|
||||||
|
|
||||||
|
codit-data-browser:
|
||||||
|
CGO_ENABLED=0 go build -x -ldflags "-X 'main.CODIT_SERVER_NAME=$(NAME)' -X 'main.CODIT_SERVER_VERSION=$(VERSION)'" -o $@ $(CODIT_DATA_BROWSER_SRCS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
go clean -x
|
||||||
|
rm -rf codit-server codit-server.debug codit-data-browser
|
||||||
572
backend/cmd/codit-data-browser/main.go
Normal file
572
backend/cmd/codit-data-browser/main.go
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "database/sql"
|
||||||
|
import "flag"
|
||||||
|
import "fmt"
|
||||||
|
import "os"
|
||||||
|
import "path/filepath"
|
||||||
|
import "sort"
|
||||||
|
import "strconv"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
import _ "modernc.org/sqlite"
|
||||||
|
import "github.com/gdamore/tcell/v2"
|
||||||
|
import "github.com/rivo/tview"
|
||||||
|
|
||||||
|
type projectInfo struct {
|
||||||
|
ID int64
|
||||||
|
PublicID string
|
||||||
|
Slug string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type repoInfo struct {
|
||||||
|
ID int64
|
||||||
|
PublicID string
|
||||||
|
ProjectID int64
|
||||||
|
Name string
|
||||||
|
RepoType string
|
||||||
|
LegacyPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
type entryInfo struct {
|
||||||
|
Name string
|
||||||
|
IsDir bool
|
||||||
|
Hint string
|
||||||
|
}
|
||||||
|
|
||||||
|
type browser struct {
|
||||||
|
DB *sql.DB
|
||||||
|
DataDir string
|
||||||
|
Cwd string
|
||||||
|
ProjectsByID map[int64]projectInfo
|
||||||
|
ReposByID map[int64]repoInfo
|
||||||
|
Entries []entryInfo
|
||||||
|
App *tview.Application
|
||||||
|
Root tview.Primitive
|
||||||
|
Header *tview.TextView
|
||||||
|
Table *tview.Table
|
||||||
|
Status *tview.TextView
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var dbPath string
|
||||||
|
var dataDir string
|
||||||
|
var err error
|
||||||
|
var br *browser
|
||||||
|
flag.StringVar(&dbPath, "db", "./codit-data/codit.db", "sqlite database path")
|
||||||
|
flag.StringVar(&dataDir, "data", "./codit-data", "codit data directory")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
br, err = newBrowser(dbPath, dataDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "init error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
err = br.run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "run error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBrowser(dbPath string, dataDir string) (*browser, error) {
|
||||||
|
var err error
|
||||||
|
var db *sql.DB
|
||||||
|
var br *browser
|
||||||
|
db, err = sql.Open("sqlite", "file:"+dbPath+"?_pragma=foreign_keys(1)")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
br = &browser{
|
||||||
|
DB: db,
|
||||||
|
DataDir: filepath.Clean(dataDir),
|
||||||
|
Cwd: filepath.Clean(dataDir),
|
||||||
|
ProjectsByID: map[int64]projectInfo{},
|
||||||
|
ReposByID: map[int64]repoInfo{},
|
||||||
|
App: tview.NewApplication(),
|
||||||
|
Header: tview.NewTextView(),
|
||||||
|
Table: tview.NewTable(),
|
||||||
|
Status: tview.NewTextView(),
|
||||||
|
}
|
||||||
|
err = br.loadMaps()
|
||||||
|
if err != nil {
|
||||||
|
_ = db.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = br.refreshEntries()
|
||||||
|
if err != nil {
|
||||||
|
_ = db.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
br.setupUI()
|
||||||
|
br.renderAll("Ready. q quit, Enter/Right open, Left/Backspace up, PgUp/PgDn/Home/End, r reload, i info, c check")
|
||||||
|
return br, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) run() error {
|
||||||
|
var err error
|
||||||
|
b.Root = b.layout()
|
||||||
|
err = b.App.SetRoot(b.Root, true).EnableMouse(false).Run()
|
||||||
|
_ = b.DB.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) layout() tview.Primitive {
|
||||||
|
var root *tview.Flex
|
||||||
|
root = tview.NewFlex().SetDirection(tview.FlexRow)
|
||||||
|
root.AddItem(b.Header, 1, 0, false)
|
||||||
|
root.AddItem(b.Table, 0, 1, true)
|
||||||
|
root.AddItem(b.Status, 1, 0, false)
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) setupUI() {
|
||||||
|
var header string
|
||||||
|
header = "Type Name Hint"
|
||||||
|
b.Header.SetDynamicColors(true)
|
||||||
|
b.Header.SetText(header)
|
||||||
|
b.Table.SetSelectable(true, false)
|
||||||
|
b.Table.SetFixed(0, 0)
|
||||||
|
b.Table.SetBorders(false)
|
||||||
|
b.Table.SetSeparator(' ')
|
||||||
|
b.Table.SetInputCapture(b.captureKey)
|
||||||
|
b.Table.SetSelectedStyle(tcell.StyleDefault.Foreground(tcell.ColorBlack).Background(tcell.ColorLightCyan))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) renderAll(status string) {
|
||||||
|
var i int
|
||||||
|
var e entryInfo
|
||||||
|
var kind string
|
||||||
|
var name string
|
||||||
|
var rel string
|
||||||
|
var err error
|
||||||
|
var row int
|
||||||
|
b.Table.Clear()
|
||||||
|
for i = 0; i < len(b.Entries); i++ {
|
||||||
|
e = b.Entries[i]
|
||||||
|
if e.IsDir {
|
||||||
|
kind = "DIR "
|
||||||
|
} else {
|
||||||
|
kind = "FILE"
|
||||||
|
}
|
||||||
|
name = e.Name
|
||||||
|
row = i
|
||||||
|
b.Table.SetCell(row, 0, tview.NewTableCell(kind).SetSelectable(false))
|
||||||
|
b.Table.SetCell(row, 1, tview.NewTableCell(name))
|
||||||
|
b.Table.SetCell(row, 2, tview.NewTableCell(e.Hint).SetSelectable(false))
|
||||||
|
}
|
||||||
|
if len(b.Entries) > 0 {
|
||||||
|
b.Table.Select(0, 1)
|
||||||
|
}
|
||||||
|
rel, err = filepath.Rel(b.DataDir, b.Cwd)
|
||||||
|
if err != nil {
|
||||||
|
rel = b.Cwd
|
||||||
|
}
|
||||||
|
if rel == "." {
|
||||||
|
rel = "/"
|
||||||
|
} else {
|
||||||
|
rel = "/" + filepath.ToSlash(rel)
|
||||||
|
}
|
||||||
|
b.Header.SetText("Path: " + rel + " (entries: " + strconv.Itoa(len(b.Entries)) + ")")
|
||||||
|
b.Status.SetText(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) captureKey(event *tcell.EventKey) *tcell.EventKey {
|
||||||
|
var key tcell.Key
|
||||||
|
var r rune
|
||||||
|
var row int
|
||||||
|
var _, _, _, h = b.Table.GetInnerRect()
|
||||||
|
var page int
|
||||||
|
var err error
|
||||||
|
var info string
|
||||||
|
var mismatches int
|
||||||
|
key = event.Key()
|
||||||
|
r = event.Rune()
|
||||||
|
if key == tcell.KeyEnter || key == tcell.KeyRight {
|
||||||
|
err = b.openSelected()
|
||||||
|
if err != nil {
|
||||||
|
b.Status.SetText("open failed: " + err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if key == tcell.KeyLeft || key == tcell.KeyBackspace || key == tcell.KeyBackspace2 {
|
||||||
|
err = b.up()
|
||||||
|
if err != nil {
|
||||||
|
b.Status.SetText("up failed: " + err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if key == tcell.KeyHome {
|
||||||
|
if len(b.Entries) > 0 {
|
||||||
|
b.Table.Select(0, 1)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if key == tcell.KeyEnd {
|
||||||
|
if len(b.Entries) > 0 {
|
||||||
|
b.Table.Select(len(b.Entries)-1, 1)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if key == tcell.KeyPgUp || key == tcell.KeyPgDn {
|
||||||
|
row, _ = b.Table.GetSelection()
|
||||||
|
page = h
|
||||||
|
if page < 1 {
|
||||||
|
page = 10
|
||||||
|
}
|
||||||
|
if key == tcell.KeyPgUp {
|
||||||
|
row = row - page
|
||||||
|
if row < 0 {
|
||||||
|
row = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
row = row + page
|
||||||
|
if row >= len(b.Entries) {
|
||||||
|
row = len(b.Entries) - 1
|
||||||
|
}
|
||||||
|
if row < 0 {
|
||||||
|
row = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(b.Entries) > 0 {
|
||||||
|
b.Table.Select(row, 1)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if r == 'q' || r == 'Q' {
|
||||||
|
b.App.Stop()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if r == 'r' || r == 'R' {
|
||||||
|
b.ProjectsByID = map[int64]projectInfo{}
|
||||||
|
b.ReposByID = map[int64]repoInfo{}
|
||||||
|
err = b.loadMaps()
|
||||||
|
if err != nil {
|
||||||
|
b.Status.SetText("reload failed: " + err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = b.refreshEntries()
|
||||||
|
if err != nil {
|
||||||
|
b.Status.SetText("reload list failed: " + err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b.renderAll("Reloaded")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if r == 'i' || r == 'I' {
|
||||||
|
info = b.selectedInfo()
|
||||||
|
b.Status.SetText(info)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if r == 'c' || r == 'C' {
|
||||||
|
mismatches = b.showMismatches()
|
||||||
|
if mismatches == 0 {
|
||||||
|
b.Status.SetText("check complete: no missing expected repo directories")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) openSelected() error {
|
||||||
|
var row int
|
||||||
|
var name string
|
||||||
|
var err error
|
||||||
|
row, _ = b.Table.GetSelection()
|
||||||
|
if row < 0 || row >= len(b.Entries) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !b.Entries[row].IsDir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name = b.Entries[row].Name
|
||||||
|
b.Cwd = filepath.Clean(filepath.Join(b.Cwd, name))
|
||||||
|
if !pathInside(b.Cwd, b.DataDir) {
|
||||||
|
return fmt.Errorf("outside data dir")
|
||||||
|
}
|
||||||
|
err = b.refreshEntries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.renderAll("Opened " + b.Cwd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) up() error {
|
||||||
|
var parent string
|
||||||
|
var err error
|
||||||
|
parent = filepath.Dir(b.Cwd)
|
||||||
|
if !pathInside(parent, b.DataDir) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b.Cwd = parent
|
||||||
|
err = b.refreshEntries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.renderAll("Opened " + b.Cwd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) selectedInfo() string {
|
||||||
|
var row int
|
||||||
|
var e entryInfo
|
||||||
|
row, _ = b.Table.GetSelection()
|
||||||
|
if row < 0 || row >= len(b.Entries) {
|
||||||
|
return "no selection"
|
||||||
|
}
|
||||||
|
e = b.Entries[row]
|
||||||
|
if e.Hint == "" {
|
||||||
|
return e.Name
|
||||||
|
}
|
||||||
|
return e.Name + " | " + e.Hint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) refreshEntries() error {
|
||||||
|
var raw []os.DirEntry
|
||||||
|
var i int
|
||||||
|
var item os.DirEntry
|
||||||
|
var entries []entryInfo
|
||||||
|
var info entryInfo
|
||||||
|
var dirs []entryInfo
|
||||||
|
var files []entryInfo
|
||||||
|
var err error
|
||||||
|
raw, err = os.ReadDir(b.Cwd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
entries = make([]entryInfo, 0, len(raw))
|
||||||
|
for i = 0; i < len(raw); i++ {
|
||||||
|
item = raw[i]
|
||||||
|
info = entryInfo{
|
||||||
|
Name: item.Name(),
|
||||||
|
IsDir: item.IsDir(),
|
||||||
|
Hint: b.resolvePathHint(item.Name()),
|
||||||
|
}
|
||||||
|
entries = append(entries, info)
|
||||||
|
}
|
||||||
|
dirs = make([]entryInfo, 0, len(entries))
|
||||||
|
files = make([]entryInfo, 0, len(entries))
|
||||||
|
for i = 0; i < len(entries); i++ {
|
||||||
|
if entries[i].IsDir {
|
||||||
|
dirs = append(dirs, entries[i])
|
||||||
|
} else {
|
||||||
|
files = append(files, entries[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Slice(dirs, func(i int, j int) bool {
|
||||||
|
return strings.ToLower(dirs[i].Name) < strings.ToLower(dirs[j].Name)
|
||||||
|
})
|
||||||
|
sort.Slice(files, func(i int, j int) bool {
|
||||||
|
return strings.ToLower(files[i].Name) < strings.ToLower(files[j].Name)
|
||||||
|
})
|
||||||
|
b.Entries = make([]entryInfo, 0, len(entries))
|
||||||
|
b.Entries = append(b.Entries, dirs...)
|
||||||
|
b.Entries = append(b.Entries, files...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) loadMaps() error {
|
||||||
|
var err error
|
||||||
|
var rows *sql.Rows
|
||||||
|
var p projectInfo
|
||||||
|
var r repoInfo
|
||||||
|
rows, err = b.DB.Query(`SELECT id, public_id, slug, name FROM projects`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
err = rows.Scan(&p.ID, &p.PublicID, &p.Slug, &p.Name)
|
||||||
|
if err != nil {
|
||||||
|
rows.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.ProjectsByID[p.ID] = p
|
||||||
|
}
|
||||||
|
err = rows.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rows, err = b.DB.Query(`SELECT id, public_id, project_id, name, type, path FROM repos`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
err = rows.Scan(&r.ID, &r.PublicID, &r.ProjectID, &r.Name, &r.RepoType, &r.LegacyPath)
|
||||||
|
if err != nil {
|
||||||
|
rows.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.ReposByID[r.ID] = r
|
||||||
|
}
|
||||||
|
err = rows.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) resolvePathHint(name string) string {
|
||||||
|
var rel string
|
||||||
|
var parts []string
|
||||||
|
var service string
|
||||||
|
var projectID int64
|
||||||
|
var repoID int64
|
||||||
|
var project projectInfo
|
||||||
|
var repo repoInfo
|
||||||
|
var err error
|
||||||
|
rel, err = filepath.Rel(b.DataDir, filepath.Join(b.Cwd, name))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
parts = strings.Split(filepath.ToSlash(rel), "/")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
service = parts[0]
|
||||||
|
projectID, err = parseStorageIDSegment(parts[1])
|
||||||
|
if err == nil {
|
||||||
|
project = b.ProjectsByID[projectID]
|
||||||
|
if project.ID > 0 && len(parts) == 2 {
|
||||||
|
return fmt.Sprintf("project: %s (%s)", project.Slug, project.PublicID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(parts) < 3 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if service == "git" {
|
||||||
|
parts[2] = strings.TrimSuffix(parts[2], ".git")
|
||||||
|
}
|
||||||
|
repoID, err = parseStorageIDSegment(parts[2])
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
repo = b.ReposByID[repoID]
|
||||||
|
if repo.ID == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("repo: %s (%s) type=%s", repo.Name, repo.PublicID, repo.RepoType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) countMismatches() int {
|
||||||
|
var ids []int64
|
||||||
|
var repoID int64
|
||||||
|
var repo repoInfo
|
||||||
|
var expected string
|
||||||
|
var err error
|
||||||
|
var count int
|
||||||
|
ids = make([]int64, 0, len(b.ReposByID))
|
||||||
|
for repoID = range b.ReposByID {
|
||||||
|
ids = append(ids, repoID)
|
||||||
|
}
|
||||||
|
sort.Slice(ids, func(i int, j int) bool { return ids[i] < ids[j] })
|
||||||
|
count = 0
|
||||||
|
for _, repoID = range ids {
|
||||||
|
repo = b.ReposByID[repoID]
|
||||||
|
expected = expectedRepoPath(b.DataDir, repo.RepoType, repo.ProjectID, repo.ID)
|
||||||
|
_, err = os.Stat(expected)
|
||||||
|
if err != nil {
|
||||||
|
count = count + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) showMismatches() int {
|
||||||
|
var lines []string
|
||||||
|
var text string
|
||||||
|
var modal *tview.Modal
|
||||||
|
lines = b.collectMismatchLines()
|
||||||
|
if len(lines) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
text = strings.Join(lines, "\n")
|
||||||
|
modal = tview.NewModal().
|
||||||
|
SetText(text).
|
||||||
|
AddButtons([]string{"Close"}).
|
||||||
|
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||||
|
b.App.SetRoot(b.Root, true).SetFocus(b.Table)
|
||||||
|
})
|
||||||
|
b.App.SetRoot(modal, true).SetFocus(modal)
|
||||||
|
return len(lines)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *browser) collectMismatchLines() []string {
|
||||||
|
var ids []int64
|
||||||
|
var repoID int64
|
||||||
|
var repo repoInfo
|
||||||
|
var project projectInfo
|
||||||
|
var expected string
|
||||||
|
var lines []string
|
||||||
|
var err error
|
||||||
|
ids = make([]int64, 0, len(b.ReposByID))
|
||||||
|
for repoID = range b.ReposByID {
|
||||||
|
ids = append(ids, repoID)
|
||||||
|
}
|
||||||
|
sort.Slice(ids, func(i int, j int) bool { return ids[i] < ids[j] })
|
||||||
|
lines = []string{}
|
||||||
|
for _, repoID = range ids {
|
||||||
|
repo = b.ReposByID[repoID]
|
||||||
|
expected = expectedRepoPath(b.DataDir, repo.RepoType, repo.ProjectID, repo.ID)
|
||||||
|
_, err = os.Stat(expected)
|
||||||
|
if err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
project = b.ProjectsByID[repo.ProjectID]
|
||||||
|
lines = append(lines, fmt.Sprintf("%s/%s [%s]", project.Slug, repo.Name, repo.RepoType))
|
||||||
|
lines = append(lines, "expected: "+expected)
|
||||||
|
lines = append(lines, "current : "+repo.LegacyPath)
|
||||||
|
lines = append(lines, "")
|
||||||
|
}
|
||||||
|
if len(lines) > 0 {
|
||||||
|
lines = lines[:len(lines)-1]
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectedRepoPath(dataDir string, repoType string, projectID int64, repoID int64) string {
|
||||||
|
var p string
|
||||||
|
var r string
|
||||||
|
p = formatStorageIDSegment(projectID)
|
||||||
|
r = formatStorageIDSegment(repoID)
|
||||||
|
if repoType == "git" {
|
||||||
|
return filepath.Join(dataDir, "git", p, r+".git")
|
||||||
|
}
|
||||||
|
if repoType == "rpm" {
|
||||||
|
return filepath.Join(dataDir, "rpm", p, r)
|
||||||
|
}
|
||||||
|
if repoType == "docker" {
|
||||||
|
return filepath.Join(dataDir, "docker", p, r)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatStorageIDSegment(id int64) string {
|
||||||
|
return fmt.Sprintf("%016x", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseStorageIDSegment(s string) (int64, error) {
|
||||||
|
var parsed int64
|
||||||
|
var err error
|
||||||
|
var trimmed string
|
||||||
|
trimmed = strings.TrimSpace(s)
|
||||||
|
parsed, err = strconv.ParseInt(trimmed, 16, 64)
|
||||||
|
if err == nil {
|
||||||
|
return parsed, nil
|
||||||
|
}
|
||||||
|
return strconv.ParseInt(trimmed, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathInside(path string, root string) bool {
|
||||||
|
var p string
|
||||||
|
var r string
|
||||||
|
var prefix string
|
||||||
|
p = filepath.Clean(path)
|
||||||
|
r = filepath.Clean(root)
|
||||||
|
if p == r {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
prefix = r + string(os.PathSeparator)
|
||||||
|
return strings.HasPrefix(p, prefix)
|
||||||
|
}
|
||||||
@@ -38,6 +38,21 @@ type gitPathRewriteHandler struct {
|
|||||||
store *db.Store
|
store *db.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type server_http_log_writer struct {
|
||||||
|
l *util.Logger
|
||||||
|
id string
|
||||||
|
depth int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hlw *server_http_log_writer) Write(p []byte) (n int, err error) {
|
||||||
|
// the standard http.Server always requires *log.Logger
|
||||||
|
// use this iowriter to create a logger to pass it to the http server.
|
||||||
|
// since this is another log write wrapper, give adjustment value
|
||||||
|
hlw.l.WriteWithCallDepth(hlw.id, util.LOG_INFO, hlw.depth, string(p))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (h *gitPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *gitPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
var path string
|
var path string
|
||||||
var parts []string
|
var parts []string
|
||||||
@@ -47,6 +62,8 @@ func (h *gitPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
var repoName string
|
var repoName string
|
||||||
var project models.Project
|
var project models.Project
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var err error
|
var err error
|
||||||
var newPath string
|
var newPath string
|
||||||
path = strings.TrimPrefix(r.URL.Path, "/")
|
path = strings.TrimPrefix(r.URL.Path, "/")
|
||||||
@@ -77,7 +94,12 @@ func (h *gitPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newPath = "/" + project.ID + "/" + repo.Name + ".git" + rest
|
projectStorageID, repoStorageID, err = h.store.GetRepoStorageIDs(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newPath = "/" + storageIDSegment(projectStorageID) + "/" + storageIDSegment(repoStorageID) + ".git" + rest
|
||||||
r.URL.Path = newPath
|
r.URL.Path = newPath
|
||||||
h.next.ServeHTTP(w, r)
|
h.next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@@ -92,6 +114,8 @@ func (h *gitIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
var parts []string
|
var parts []string
|
||||||
var rest string
|
var rest string
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var err error
|
var err error
|
||||||
var newPath string
|
var newPath string
|
||||||
var repoID string
|
var repoID string
|
||||||
@@ -107,6 +131,11 @@ func (h *gitIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
projectStorageID, repoStorageID, err = h.store.GetRepoStorageIDs(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(parts) == 3 {
|
if len(parts) == 3 {
|
||||||
rest = "/" + parts[1] + "/" + parts[2]
|
rest = "/" + parts[1] + "/" + parts[2]
|
||||||
} else if len(parts) == 2 {
|
} else if len(parts) == 2 {
|
||||||
@@ -114,7 +143,7 @@ func (h *gitIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
} else {
|
} else {
|
||||||
rest = ""
|
rest = ""
|
||||||
}
|
}
|
||||||
newPath = "/" + repo.ProjectID + "/" + repo.Name + ".git" + rest
|
newPath = "/" + storageIDSegment(projectStorageID) + "/" + storageIDSegment(repoStorageID) + ".git" + rest
|
||||||
r.URL.Path = newPath
|
r.URL.Path = newPath
|
||||||
h.next.ServeHTTP(w, r)
|
h.next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@@ -132,6 +161,8 @@ func (h *rpmPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
var rest string
|
var rest string
|
||||||
var project models.Project
|
var project models.Project
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var err error
|
var err error
|
||||||
var newPath string
|
var newPath string
|
||||||
path = strings.TrimPrefix(r.URL.Path, "/")
|
path = strings.TrimPrefix(r.URL.Path, "/")
|
||||||
@@ -161,7 +192,12 @@ func (h *rpmPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newPath = "/" + project.ID + "/" + repo.Name + rest
|
projectStorageID, repoStorageID, err = h.store.GetRepoStorageIDs(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newPath = "/" + storageIDSegment(projectStorageID) + "/" + storageIDSegment(repoStorageID) + rest
|
||||||
r.URL.Path = newPath
|
r.URL.Path = newPath
|
||||||
h.next.ServeHTTP(w, r)
|
h.next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@@ -176,6 +212,8 @@ func (h *rpmIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
var parts []string
|
var parts []string
|
||||||
var rest string
|
var rest string
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var err error
|
var err error
|
||||||
var newPath string
|
var newPath string
|
||||||
var repoID string
|
var repoID string
|
||||||
@@ -191,6 +229,11 @@ func (h *rpmIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
projectStorageID, repoStorageID, err = h.store.GetRepoStorageIDs(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
if len(parts) == 3 {
|
if len(parts) == 3 {
|
||||||
rest = "/" + parts[1] + "/" + parts[2]
|
rest = "/" + parts[1] + "/" + parts[2]
|
||||||
} else if len(parts) == 2 {
|
} else if len(parts) == 2 {
|
||||||
@@ -198,11 +241,15 @@ func (h *rpmIDPathRewriteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||||||
} else {
|
} else {
|
||||||
rest = ""
|
rest = ""
|
||||||
}
|
}
|
||||||
newPath = "/" + repo.ProjectID + "/" + repo.Name + rest
|
newPath = "/" + storageIDSegment(projectStorageID) + "/" + storageIDSegment(repoStorageID) + rest
|
||||||
r.URL.Path = newPath
|
r.URL.Path = newPath
|
||||||
h.next.ServeHTTP(w, r)
|
h.next.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func storageIDSegment(id int64) string {
|
||||||
|
return fmt.Sprintf("%016x", id)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var configPath string
|
var configPath string
|
||||||
var cfg config.Config
|
var cfg config.Config
|
||||||
@@ -766,6 +813,7 @@ func (m *additionalListenerManager) startEndpoint(endpoint listenerEndpoint) run
|
|||||||
Addr: endpoint.Addr,
|
Addr: endpoint.Addr,
|
||||||
Handler: m.Handler,
|
Handler: m.Handler,
|
||||||
ConnContext: connContextWithListenerPolicy(endpoint.Policy),
|
ConnContext: connContextWithListenerPolicy(endpoint.Policy),
|
||||||
|
ErrorLog: log.New(&server_http_log_writer{l: m.Logger, id: endpoint.Name, depth: +2}, "", 0),
|
||||||
}
|
}
|
||||||
if endpoint.IsHTTPS {
|
if endpoint.IsHTTPS {
|
||||||
server.TLSConfig = endpoint.TLSConfig
|
server.TLSConfig = endpoint.TLSConfig
|
||||||
@@ -776,9 +824,9 @@ func (m *additionalListenerManager) startEndpoint(endpoint listenerEndpoint) run
|
|||||||
}
|
}
|
||||||
if m.Logger != nil {
|
if m.Logger != nil {
|
||||||
if endpoint.IsHTTPS {
|
if endpoint.IsHTTPS {
|
||||||
m.Logger.Write("", util.LOG_INFO, "additional listener started name=%s https://%s", endpoint.Name, endpoint.Addr)
|
m.Logger.Write(endpoint.Name, util.LOG_INFO, "additional listener started https://%s", endpoint.Addr)
|
||||||
} else {
|
} else {
|
||||||
m.Logger.Write("", util.LOG_INFO, "additional listener started name=%s %s", endpoint.Name, endpoint.Addr)
|
m.Logger.Write(endpoint.Name, util.LOG_INFO, "additional listener started %s", endpoint.Addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go func(ep listenerEndpoint, srv *http.Server) {
|
go func(ep listenerEndpoint, srv *http.Server) {
|
||||||
@@ -789,7 +837,7 @@ func (m *additionalListenerManager) startEndpoint(endpoint listenerEndpoint) run
|
|||||||
err = srv.ListenAndServe()
|
err = srv.ListenAndServe()
|
||||||
}
|
}
|
||||||
if err != nil && !errors.Is(err, http.ErrServerClosed) && m.Logger != nil {
|
if err != nil && !errors.Is(err, http.ErrServerClosed) && m.Logger != nil {
|
||||||
m.Logger.Write("", util.LOG_ERROR, "additional listener failed name=%s addr=%s err=%v", ep.Name, ep.Addr, err)
|
m.Logger.Write(ep.Name, util.LOG_ERROR, "additional listener failed addr=%s err=%v", ep.Addr, err)
|
||||||
}
|
}
|
||||||
}(endpoint, server)
|
}(endpoint, server)
|
||||||
return running
|
return running
|
||||||
@@ -1296,12 +1344,26 @@ func serveListeners(endpoints []listenerEndpoint, handler http.Handler, logger *
|
|||||||
go func(endpoint listenerEndpoint) {
|
go func(endpoint listenerEndpoint) {
|
||||||
var err error
|
var err error
|
||||||
var server *http.Server
|
var server *http.Server
|
||||||
|
var l *log.Logger
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
|
l = log.New(&server_http_log_writer{l: logger, id: "", depth: +2}, "", 0)
|
||||||
if endpoint.IsHTTPS {
|
if endpoint.IsHTTPS {
|
||||||
server = &http.Server{Addr: endpoint.Addr, Handler: handler, TLSConfig: endpoint.TLSConfig, ConnContext: connContextWithListenerPolicy(endpoint.Policy)}
|
server = &http.Server{
|
||||||
|
Addr: endpoint.Addr,
|
||||||
|
Handler: handler,
|
||||||
|
TLSConfig: endpoint.TLSConfig,
|
||||||
|
ErrorLog: l,
|
||||||
|
ConnContext: connContextWithListenerPolicy(endpoint.Policy),
|
||||||
|
}
|
||||||
err = server.ListenAndServeTLS("", "")
|
err = server.ListenAndServeTLS("", "")
|
||||||
} else {
|
} else {
|
||||||
server = &http.Server{Addr: endpoint.Addr, Handler: handler, ConnContext: connContextWithListenerPolicy(endpoint.Policy)}
|
server = &http.Server{
|
||||||
|
Addr: endpoint.Addr,
|
||||||
|
Handler: handler,
|
||||||
|
ErrorLog: l,
|
||||||
|
ConnContext: connContextWithListenerPolicy(endpoint.Policy),
|
||||||
|
}
|
||||||
err = server.ListenAndServe()
|
err = server.ListenAndServe()
|
||||||
}
|
}
|
||||||
errs <- err
|
errs <- err
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ module codit
|
|||||||
go 1.25.3
|
go 1.25.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/gdamore/tcell/v2 v2.13.8
|
||||||
github.com/go-git/go-git/v5 v5.12.0
|
github.com/go-git/go-git/v5 v5.12.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
github.com/graphql-go/graphql v0.8.0
|
github.com/graphql-go/graphql v0.8.0
|
||||||
|
github.com/rivo/tview v0.42.0
|
||||||
github.com/sosedoff/gitkit v0.4.0
|
github.com/sosedoff/gitkit v0.4.0
|
||||||
golang.org/x/crypto v0.47.0
|
golang.org/x/crypto v0.47.0
|
||||||
modernc.org/sqlite v1.30.0
|
modernc.org/sqlite v1.30.0
|
||||||
@@ -22,6 +24,7 @@ require (
|
|||||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
|
github.com/gdamore/encoding v1.0.1 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||||
@@ -32,19 +35,24 @@ require (
|
|||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.3 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sassoftware/go-rpmutils v0.4.1-0.20250318174028-2660c86d578c // indirect
|
github.com/sassoftware/go-rpmutils v0.4.1-0.20250318174028-2660c86d578c // indirect
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.15 // indirect
|
github.com/ulikunitz/xz v0.5.15 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
golang.org/x/mod v0.16.0 // indirect
|
golang.org/x/mod v0.31.0 // indirect
|
||||||
golang.org/x/net v0.48.0 // indirect
|
golang.org/x/net v0.48.0 // indirect
|
||||||
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.40.0 // indirect
|
||||||
golang.org/x/tools v0.19.0 // indirect
|
golang.org/x/term v0.39.0 // indirect
|
||||||
|
golang.org/x/text v0.33.0 // indirect
|
||||||
|
golang.org/x/tools v0.40.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||||
modernc.org/libc v1.50.9 // indirect
|
modernc.org/libc v1.50.9 // indirect
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej
|
|||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
|
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
||||||
|
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
||||||
|
github.com/gdamore/tcell/v2 v2.13.8 h1:Mys/Kl5wfC/GcC5Cx4C2BIQH9dbnhnkPgS9/wF3RlfU=
|
||||||
|
github.com/gdamore/tcell/v2 v2.13.8/go.mod h1:+Wfe208WDdB7INEtCsNrAN6O2m+wsTPk1RAovjaILlo=
|
||||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||||
@@ -70,6 +74,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
@@ -84,6 +90,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/rivo/tview v0.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c=
|
||||||
|
github.com/rivo/tview v0.42.0/go.mod h1:cSfIYfhpSGCjp3r/ECJb+GKS7cGJnqV8vfjQPwoXyfY=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
github.com/sassoftware/go-rpmutils v0.4.1-0.20250318174028-2660c86d578c h1:Y+MtXJBE7rpqj0nk6GhSzD/48pXSKNEJPIYhtoSCbjk=
|
github.com/sassoftware/go-rpmutils v0.4.1-0.20250318174028-2660c86d578c h1:Y+MtXJBE7rpqj0nk6GhSzD/48pXSKNEJPIYhtoSCbjk=
|
||||||
@@ -120,8 +130,8 @@ golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
|||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
@@ -133,8 +143,8 @@ golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
|||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -164,14 +174,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ func (s *Store) ListPKICAs() ([]models.PKICA, error) {
|
|||||||
var err error
|
var err error
|
||||||
var items []models.PKICA
|
var items []models.PKICA
|
||||||
var item models.PKICA
|
var item models.PKICA
|
||||||
rows, err = s.DB.Query(`SELECT id, name, COALESCE(parent_ca_id, ''), is_root, cert_pem, key_pem, serial_counter, status, created_at, updated_at FROM pki_cas ORDER BY name`)
|
rows, err = s.DB.Query(`SELECT c.public_id, c.name, COALESCE(p.public_id, ''), c.is_root, c.cert_pem, c.key_pem, c.serial_counter, c.status, c.created_at, c.updated_at
|
||||||
|
FROM pki_cas c
|
||||||
|
LEFT JOIN pki_cas p ON p.id = c.parent_ca_id
|
||||||
|
ORDER BY c.name`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -35,7 +38,10 @@ func (s *Store) GetPKICA(id string) (models.PKICA, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var item models.PKICA
|
var item models.PKICA
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, name, COALESCE(parent_ca_id, ''), is_root, cert_pem, key_pem, serial_counter, status, created_at, updated_at FROM pki_cas WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT c.public_id, c.name, COALESCE(p.public_id, ''), c.is_root, c.cert_pem, c.key_pem, c.serial_counter, c.status, c.created_at, c.updated_at
|
||||||
|
FROM pki_cas c
|
||||||
|
LEFT JOIN pki_cas p ON p.id = c.parent_ca_id
|
||||||
|
WHERE c.public_id = ?`, id)
|
||||||
err = row.Scan(&item.ID, &item.Name, &item.ParentCAID, &item.IsRoot, &item.CertPEM, &item.KeyPEM, &item.SerialCounter, &item.Status, &item.CreatedAt, &item.UpdatedAt)
|
err = row.Scan(&item.ID, &item.Name, &item.ParentCAID, &item.IsRoot, &item.CertPEM, &item.KeyPEM, &item.SerialCounter, &item.Status, &item.CreatedAt, &item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -45,14 +51,13 @@ func (s *Store) GetPKICA(id string) (models.PKICA, error) {
|
|||||||
|
|
||||||
func (s *Store) UpdatePKICAName(id string, name string) error {
|
func (s *Store) UpdatePKICAName(id string, name string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE pki_cas SET name = ?, updated_at = ? WHERE id = ?`, name, time.Now().UTC().Unix(), id)
|
_, err = s.DB.Exec(`UPDATE pki_cas SET name = ?, updated_at = ? WHERE public_id = ?`, name, time.Now().UTC().Unix(), id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreatePKICA(item models.PKICA) (models.PKICA, error) {
|
func (s *Store) CreatePKICA(item models.PKICA) (models.PKICA, error) {
|
||||||
var id string
|
var id string
|
||||||
var now int64
|
var now int64
|
||||||
var parentValue any
|
|
||||||
var err error
|
var err error
|
||||||
if item.ID == "" {
|
if item.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -70,12 +75,9 @@ func (s *Store) CreatePKICA(item models.PKICA) (models.PKICA, error) {
|
|||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.CreatedAt = now
|
item.CreatedAt = now
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
parentValue = nil
|
_, err = s.DB.Exec(`INSERT INTO pki_cas (public_id, name, parent_ca_id, is_root, cert_pem, key_pem, serial_counter, status, created_at, updated_at)
|
||||||
if item.ParentCAID != "" {
|
VALUES (?, ?, CASE WHEN ? = '' THEN NULL ELSE (SELECT id FROM pki_cas WHERE public_id = ?) END, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
parentValue = item.ParentCAID
|
item.ID, item.Name, item.ParentCAID, item.ParentCAID, item.IsRoot, item.CertPEM, item.KeyPEM, item.SerialCounter, item.Status, item.CreatedAt, item.UpdatedAt)
|
||||||
}
|
|
||||||
_, err = s.DB.Exec(`INSERT INTO pki_cas (id, name, parent_ca_id, is_root, cert_pem, key_pem, serial_counter, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
||||||
item.ID, item.Name, parentValue, item.IsRoot, item.CertPEM, item.KeyPEM, item.SerialCounter, item.Status, item.CreatedAt, item.UpdatedAt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
@@ -86,7 +88,10 @@ func (s *Store) CountPKICAChildren(id string) (int, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var count int
|
var count int
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT COUNT(*) FROM pki_cas WHERE parent_ca_id = ?`, id)
|
row = s.DB.QueryRow(`SELECT COUNT(*)
|
||||||
|
FROM pki_cas c
|
||||||
|
JOIN pki_cas p ON p.id = c.parent_ca_id
|
||||||
|
WHERE p.public_id = ?`, id)
|
||||||
err = row.Scan(&count)
|
err = row.Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -98,7 +103,10 @@ func (s *Store) CountPKICertsByCA(id string) (int, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var count int
|
var count int
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT COUNT(*) FROM pki_certs WHERE ca_id = ?`, id)
|
row = s.DB.QueryRow(`SELECT COUNT(*)
|
||||||
|
FROM pki_certs c
|
||||||
|
JOIN pki_cas ca ON ca.id = c.ca_id
|
||||||
|
WHERE ca.public_id = ?`, id)
|
||||||
err = row.Scan(&count)
|
err = row.Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -108,7 +116,7 @@ func (s *Store) CountPKICertsByCA(id string) (int, error) {
|
|||||||
|
|
||||||
func (s *Store) DeletePKICA(id string) error {
|
func (s *Store) DeletePKICA(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM pki_cas WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM pki_cas WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +125,7 @@ func (s *Store) DeletePKICASubtree(id string) error {
|
|||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
var err error
|
var err error
|
||||||
var itemID string
|
var itemID string
|
||||||
var parentID sql.NullString
|
var parentID string
|
||||||
var parentByID map[string]string
|
var parentByID map[string]string
|
||||||
var pending []string
|
var pending []string
|
||||||
var current string
|
var current string
|
||||||
@@ -131,7 +139,9 @@ func (s *Store) DeletePKICASubtree(id string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rows, err = tx.Query(`SELECT id, parent_ca_id FROM pki_cas`)
|
rows, err = tx.Query(`SELECT c.public_id, COALESCE(p.public_id, '')
|
||||||
|
FROM pki_cas c
|
||||||
|
LEFT JOIN pki_cas p ON p.id = c.parent_ca_id`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
@@ -143,11 +153,7 @@ func (s *Store) DeletePKICASubtree(id string) error {
|
|||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if parentID.Valid {
|
parentByID[itemID] = parentID
|
||||||
parentByID[itemID] = parentID.String
|
|
||||||
} else {
|
|
||||||
parentByID[itemID] = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
err = rows.Err()
|
err = rows.Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -177,7 +183,7 @@ func (s *Store) DeletePKICASubtree(id string) error {
|
|||||||
for i = len(toDelete) - 1; i >= 0; i-- {
|
for i = len(toDelete) - 1; i >= 0; i-- {
|
||||||
j = i
|
j = i
|
||||||
_ = j
|
_ = j
|
||||||
_, err = tx.Exec(`DELETE FROM pki_cas WHERE id = ?`, toDelete[i])
|
_, err = tx.Exec(`DELETE FROM pki_cas WHERE public_id = ?`, toDelete[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
@@ -199,13 +205,13 @@ func (s *Store) NextPKICASerial(caID string) (int64, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
row = tx.QueryRow(`SELECT serial_counter FROM pki_cas WHERE id = ?`, caID)
|
row = tx.QueryRow(`SELECT serial_counter FROM pki_cas WHERE public_id = ?`, caID)
|
||||||
err = row.Scan(&serial)
|
err = row.Scan(&serial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`UPDATE pki_cas SET serial_counter = ?, updated_at = ? WHERE id = ?`, serial+1, time.Now().UTC().Unix(), caID)
|
_, err = tx.Exec(`UPDATE pki_cas SET serial_counter = ?, updated_at = ? WHERE public_id = ?`, serial+1, time.Now().UTC().Unix(), caID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -223,11 +229,22 @@ func (s *Store) ListPKICerts(caID string) ([]models.PKICert, error) {
|
|||||||
var items []models.PKICert
|
var items []models.PKICert
|
||||||
var item models.PKICert
|
var item models.PKICert
|
||||||
if caID == "" {
|
if caID == "" {
|
||||||
rows, err = s.DB.Query(`SELECT id, COALESCE(ca_id, ''), serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at FROM pki_certs ORDER BY created_at DESC`)
|
rows, err = s.DB.Query(`SELECT c.public_id, COALESCE(ca.public_id, ''), c.serial_hex, c.common_name, c.san_dns, c.san_ips, c.is_ca, c.cert_pem, c.key_pem, c.not_before, c.not_after, c.status, c.revoked_at, c.revocation_reason, c.created_at
|
||||||
|
FROM pki_certs c
|
||||||
|
LEFT JOIN pki_cas ca ON ca.id = c.ca_id
|
||||||
|
ORDER BY c.created_at DESC`)
|
||||||
} else if caID == "standalone" {
|
} else if caID == "standalone" {
|
||||||
rows, err = s.DB.Query(`SELECT id, COALESCE(ca_id, ''), serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at FROM pki_certs WHERE ca_id IS NULL OR ca_id = '' ORDER BY created_at DESC`)
|
rows, err = s.DB.Query(`SELECT c.public_id, COALESCE(ca.public_id, ''), c.serial_hex, c.common_name, c.san_dns, c.san_ips, c.is_ca, c.cert_pem, c.key_pem, c.not_before, c.not_after, c.status, c.revoked_at, c.revocation_reason, c.created_at
|
||||||
|
FROM pki_certs c
|
||||||
|
LEFT JOIN pki_cas ca ON ca.id = c.ca_id
|
||||||
|
WHERE c.ca_id IS NULL
|
||||||
|
ORDER BY c.created_at DESC`)
|
||||||
} else {
|
} else {
|
||||||
rows, err = s.DB.Query(`SELECT id, COALESCE(ca_id, ''), serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at FROM pki_certs WHERE ca_id = ? ORDER BY created_at DESC`, caID)
|
rows, err = s.DB.Query(`SELECT c.public_id, COALESCE(ca.public_id, ''), c.serial_hex, c.common_name, c.san_dns, c.san_ips, c.is_ca, c.cert_pem, c.key_pem, c.not_before, c.not_after, c.status, c.revoked_at, c.revocation_reason, c.created_at
|
||||||
|
FROM pki_certs c
|
||||||
|
LEFT JOIN pki_cas ca ON ca.id = c.ca_id
|
||||||
|
WHERE c.ca_id = (SELECT id FROM pki_cas WHERE public_id = ?)
|
||||||
|
ORDER BY c.created_at DESC`, caID)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -251,7 +268,10 @@ func (s *Store) GetPKICert(id string) (models.PKICert, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var item models.PKICert
|
var item models.PKICert
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, COALESCE(ca_id, ''), serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at FROM pki_certs WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT c.public_id, COALESCE(ca.public_id, ''), c.serial_hex, c.common_name, c.san_dns, c.san_ips, c.is_ca, c.cert_pem, c.key_pem, c.not_before, c.not_after, c.status, c.revoked_at, c.revocation_reason, c.created_at
|
||||||
|
FROM pki_certs c
|
||||||
|
LEFT JOIN pki_cas ca ON ca.id = c.ca_id
|
||||||
|
WHERE c.public_id = ?`, id)
|
||||||
err = row.Scan(&item.ID, &item.CAID, &item.SerialHex, &item.CommonName, &item.SANDNS, &item.SANIPs, &item.IsCA, &item.CertPEM, &item.KeyPEM, &item.NotBefore, &item.NotAfter, &item.Status, &item.RevokedAt, &item.RevocationReason, &item.CreatedAt)
|
err = row.Scan(&item.ID, &item.CAID, &item.SerialHex, &item.CommonName, &item.SANDNS, &item.SANIPs, &item.IsCA, &item.CertPEM, &item.KeyPEM, &item.NotBefore, &item.NotAfter, &item.Status, &item.RevokedAt, &item.RevocationReason, &item.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -262,7 +282,6 @@ func (s *Store) GetPKICert(id string) (models.PKICert, error) {
|
|||||||
func (s *Store) CreatePKICert(item models.PKICert) (models.PKICert, error) {
|
func (s *Store) CreatePKICert(item models.PKICert) (models.PKICert, error) {
|
||||||
var id string
|
var id string
|
||||||
var now int64
|
var now int64
|
||||||
var caIDValue any
|
|
||||||
var err error
|
var err error
|
||||||
if item.ID == "" {
|
if item.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -276,12 +295,10 @@ func (s *Store) CreatePKICert(item models.PKICert) (models.PKICert, error) {
|
|||||||
}
|
}
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.CreatedAt = now
|
item.CreatedAt = now
|
||||||
caIDValue = nil
|
item.CAID = strings.TrimSpace(item.CAID)
|
||||||
if strings.TrimSpace(item.CAID) != "" {
|
_, err = s.DB.Exec(`INSERT INTO pki_certs (public_id, ca_id, serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at)
|
||||||
caIDValue = strings.TrimSpace(item.CAID)
|
VALUES (?, CASE WHEN ? = '' THEN NULL ELSE (SELECT id FROM pki_cas WHERE public_id = ?) END, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
}
|
item.ID, item.CAID, item.CAID, item.SerialHex, item.CommonName, item.SANDNS, item.SANIPs, item.IsCA, item.CertPEM, item.KeyPEM, item.NotBefore, item.NotAfter, item.Status, item.RevokedAt, item.RevocationReason, item.CreatedAt)
|
||||||
_, err = s.DB.Exec(`INSERT INTO pki_certs (id, ca_id, serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem, not_before, not_after, status, revoked_at, revocation_reason, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
||||||
item.ID, caIDValue, item.SerialHex, item.CommonName, item.SANDNS, item.SANIPs, item.IsCA, item.CertPEM, item.KeyPEM, item.NotBefore, item.NotAfter, item.Status, item.RevokedAt, item.RevocationReason, item.CreatedAt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
@@ -290,13 +307,13 @@ func (s *Store) CreatePKICert(item models.PKICert) (models.PKICert, error) {
|
|||||||
|
|
||||||
func (s *Store) RevokePKICert(id string, reason string) error {
|
func (s *Store) RevokePKICert(id string, reason string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE pki_certs SET status = 'revoked', revoked_at = ?, revocation_reason = ? WHERE id = ?`, time.Now().UTC().Unix(), reason, id)
|
_, err = s.DB.Exec(`UPDATE pki_certs SET status = 'revoked', revoked_at = ?, revocation_reason = ? WHERE public_id = ?`, time.Now().UTC().Unix(), reason, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeletePKICert(id string) error {
|
func (s *Store) DeletePKICert(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM pki_certs WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM pki_certs WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func (s *Store) ListServicePrincipals() ([]models.ServicePrincipal, error) {
|
|||||||
var items []models.ServicePrincipal
|
var items []models.ServicePrincipal
|
||||||
var item models.ServicePrincipal
|
var item models.ServicePrincipal
|
||||||
var err error
|
var err error
|
||||||
rows, err = s.DB.Query(`SELECT id, name, description, is_admin, disabled, created_at, updated_at FROM service_principals ORDER BY name`)
|
rows, err = s.DB.Query(`SELECT public_id, name, description, is_admin, disabled, created_at, updated_at FROM service_principals ORDER BY name`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ func (s *Store) GetServicePrincipal(id string) (models.ServicePrincipal, error)
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var item models.ServicePrincipal
|
var item models.ServicePrincipal
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, name, description, is_admin, disabled, created_at, updated_at FROM service_principals WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT public_id, name, description, is_admin, disabled, created_at, updated_at FROM service_principals WHERE public_id = ?`, id)
|
||||||
err = row.Scan(&item.ID, &item.Name, &item.Description, &item.IsAdmin, &item.Disabled, &item.CreatedAt, &item.UpdatedAt)
|
err = row.Scan(&item.ID, &item.Name, &item.Description, &item.IsAdmin, &item.Disabled, &item.CreatedAt, &item.UpdatedAt)
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func (s *Store) CreateServicePrincipal(item models.ServicePrincipal) (models.Ser
|
|||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.CreatedAt = now
|
item.CreatedAt = now
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
_, err = s.DB.Exec(`INSERT INTO service_principals (id, name, description, is_admin, disabled, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO service_principals (public_id, name, description, is_admin, disabled, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||||
item.ID, item.Name, item.Description, item.IsAdmin, item.Disabled, item.CreatedAt, item.UpdatedAt)
|
item.ID, item.Name, item.Description, item.IsAdmin, item.Disabled, item.CreatedAt, item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -67,14 +67,14 @@ func (s *Store) UpdateServicePrincipal(item models.ServicePrincipal) error {
|
|||||||
var err error
|
var err error
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
_, err = s.DB.Exec(`UPDATE service_principals SET name = ?, description = ?, is_admin = ?, disabled = ?, updated_at = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE service_principals SET name = ?, description = ?, is_admin = ?, disabled = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
item.Name, item.Description, item.IsAdmin, item.Disabled, item.UpdatedAt, item.ID)
|
item.Name, item.Description, item.IsAdmin, item.Disabled, item.UpdatedAt, item.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteServicePrincipal(id string) error {
|
func (s *Store) DeleteServicePrincipal(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM service_principals WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM service_principals WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,10 @@ func (s *Store) ListCertPrincipalBindings() ([]models.CertPrincipalBinding, erro
|
|||||||
var items []models.CertPrincipalBinding
|
var items []models.CertPrincipalBinding
|
||||||
var item models.CertPrincipalBinding
|
var item models.CertPrincipalBinding
|
||||||
var err error
|
var err error
|
||||||
rows, err = s.DB.Query(`SELECT fingerprint, principal_id, enabled, created_at, updated_at FROM cert_principal_bindings ORDER BY fingerprint`)
|
rows, err = s.DB.Query(`SELECT b.fingerprint, p.public_id, b.enabled, b.created_at, b.updated_at
|
||||||
|
FROM cert_principal_bindings b
|
||||||
|
JOIN service_principals p ON p.id = b.principal_id
|
||||||
|
ORDER BY b.fingerprint`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -109,7 +112,7 @@ func (s *Store) UpsertCertPrincipalBinding(item models.CertPrincipalBinding) (mo
|
|||||||
item.Fingerprint = strings.ToLower(strings.TrimSpace(item.Fingerprint))
|
item.Fingerprint = strings.ToLower(strings.TrimSpace(item.Fingerprint))
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
_, err = s.DB.Exec(`INSERT INTO cert_principal_bindings (fingerprint, principal_id, enabled, created_at, updated_at)
|
_, err = s.DB.Exec(`INSERT INTO cert_principal_bindings (fingerprint, principal_id, enabled, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, (SELECT id FROM service_principals WHERE public_id = ?), ?, ?, ?)
|
||||||
ON CONFLICT(fingerprint) DO UPDATE SET principal_id = excluded.principal_id, enabled = excluded.enabled, updated_at = excluded.updated_at`,
|
ON CONFLICT(fingerprint) DO UPDATE SET principal_id = excluded.principal_id, enabled = excluded.enabled, updated_at = excluded.updated_at`,
|
||||||
item.Fingerprint, item.PrincipalID, item.Enabled, now, now)
|
item.Fingerprint, item.PrincipalID, item.Enabled, now, now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -132,7 +135,7 @@ func (s *Store) GetPrincipalByCertFingerprint(fingerprint string) (models.Servic
|
|||||||
var enabled bool
|
var enabled bool
|
||||||
var err error
|
var err error
|
||||||
fingerprint = strings.ToLower(strings.TrimSpace(fingerprint))
|
fingerprint = strings.ToLower(strings.TrimSpace(fingerprint))
|
||||||
row = s.DB.QueryRow(`SELECT p.id, p.name, p.description, p.is_admin, p.disabled, p.created_at, p.updated_at, b.enabled
|
row = s.DB.QueryRow(`SELECT p.public_id, p.name, p.description, p.is_admin, p.disabled, p.created_at, p.updated_at, b.enabled
|
||||||
FROM cert_principal_bindings b
|
FROM cert_principal_bindings b
|
||||||
INNER JOIN service_principals p ON p.id = b.principal_id
|
INNER JOIN service_principals p ON p.id = b.principal_id
|
||||||
WHERE b.fingerprint = ?`, fingerprint)
|
WHERE b.fingerprint = ?`, fingerprint)
|
||||||
@@ -154,7 +157,12 @@ func (s *Store) ListPrincipalProjectRoles(principalID string) ([]models.Principa
|
|||||||
var items []models.PrincipalProjectRole
|
var items []models.PrincipalProjectRole
|
||||||
var item models.PrincipalProjectRole
|
var item models.PrincipalProjectRole
|
||||||
var err error
|
var err error
|
||||||
rows, err = s.DB.Query(`SELECT principal_id, project_id, role, created_at FROM principal_project_roles WHERE principal_id = ? ORDER BY project_id`, principalID)
|
rows, err = s.DB.Query(`SELECT sp.public_id, p.public_id, r.role, r.created_at
|
||||||
|
FROM principal_project_roles r
|
||||||
|
JOIN service_principals sp ON sp.id = r.principal_id
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
WHERE r.principal_id = (SELECT id FROM service_principals WHERE public_id = ?)
|
||||||
|
ORDER BY p.public_id`, principalID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -178,7 +186,8 @@ func (s *Store) UpsertPrincipalProjectRole(item models.PrincipalProjectRole) (mo
|
|||||||
var err error
|
var err error
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.CreatedAt = now
|
item.CreatedAt = now
|
||||||
_, err = s.DB.Exec(`INSERT INTO principal_project_roles (principal_id, project_id, role, created_at) VALUES (?, ?, ?, ?)
|
_, err = s.DB.Exec(`INSERT INTO principal_project_roles (principal_id, project_id, role, created_at)
|
||||||
|
VALUES ((SELECT id FROM service_principals WHERE public_id = ?), (SELECT id FROM projects WHERE public_id = ?), ?, ?)
|
||||||
ON CONFLICT(principal_id, project_id) DO UPDATE SET role = excluded.role`,
|
ON CONFLICT(principal_id, project_id) DO UPDATE SET role = excluded.role`,
|
||||||
item.PrincipalID, item.ProjectID, item.Role, item.CreatedAt)
|
item.PrincipalID, item.ProjectID, item.Role, item.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -189,7 +198,9 @@ func (s *Store) UpsertPrincipalProjectRole(item models.PrincipalProjectRole) (mo
|
|||||||
|
|
||||||
func (s *Store) DeletePrincipalProjectRole(principalID string, projectID string) error {
|
func (s *Store) DeletePrincipalProjectRole(principalID string, projectID string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM principal_project_roles WHERE principal_id = ? AND project_id = ?`, principalID, projectID)
|
_, err = s.DB.Exec(`DELETE FROM principal_project_roles
|
||||||
|
WHERE principal_id = (SELECT id FROM service_principals WHERE public_id = ?)
|
||||||
|
AND project_id = (SELECT id FROM projects WHERE public_id = ?)`, principalID, projectID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +208,9 @@ func (s *Store) GetPrincipalProjectRole(principalID string, projectID string) (s
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var role string
|
var role string
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT role FROM principal_project_roles WHERE principal_id = ? AND project_id = ?`, principalID, projectID)
|
row = s.DB.QueryRow(`SELECT role FROM principal_project_roles
|
||||||
|
WHERE principal_id = (SELECT id FROM service_principals WHERE public_id = ?)
|
||||||
|
AND project_id = (SELECT id FROM projects WHERE public_id = ?)`, principalID, projectID)
|
||||||
err = row.Scan(&role)
|
err = row.Scan(&role)
|
||||||
return role, err
|
return role, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ func (s *Store) ListRPMRepoDirs(repoID string) ([]models.RPMRepoDir, error) {
|
|||||||
var items []models.RPMRepoDir
|
var items []models.RPMRepoDir
|
||||||
var item models.RPMRepoDir
|
var item models.RPMRepoDir
|
||||||
var err error
|
var err error
|
||||||
rows, err = s.DB.Query(`SELECT repo_id, path, mode, allow_delete, remote_url, connect_host, host_header, tls_server_name, tls_insecure_skip_verify, sync_interval_sec, sync_enabled, dirty, next_sync_at, sync_running, sync_status, sync_error, sync_step, sync_total, sync_done, sync_failed, sync_deleted, last_sync_started_at, last_sync_finished_at, last_sync_success_at, last_synced_revision, created_at, updated_at FROM rpm_repo_dirs WHERE repo_id = ? ORDER BY LENGTH(path), path`, repoID)
|
rows, err = s.DB.Query(`SELECT r.public_id, d.path, d.mode, d.allow_delete, d.remote_url, d.connect_host, d.host_header, d.tls_server_name, d.tls_insecure_skip_verify, d.sync_interval_sec, d.sync_enabled, d.dirty, d.next_sync_at, d.sync_running, d.sync_status, d.sync_error, d.sync_step, d.sync_total, d.sync_done, d.sync_failed, d.sync_deleted, d.last_sync_started_at, d.last_sync_finished_at, d.last_sync_success_at, d.last_synced_revision, d.created_at, d.updated_at
|
||||||
|
FROM rpm_repo_dirs d
|
||||||
|
JOIN repos r ON r.id = d.repo_id
|
||||||
|
WHERE r.public_id = ?
|
||||||
|
ORDER BY LENGTH(d.path), d.path`, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -40,7 +44,7 @@ func (s *Store) UpsertRPMRepoDir(item models.RPMRepoDir) error {
|
|||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`
|
_, err = s.DB.Exec(`
|
||||||
INSERT INTO rpm_repo_dirs (repo_id, path, mode, allow_delete, remote_url, connect_host, host_header, tls_server_name, tls_insecure_skip_verify, sync_interval_sec, sync_enabled, dirty, next_sync_at, created_at, updated_at)
|
INSERT INTO rpm_repo_dirs (repo_id, path, mode, allow_delete, remote_url, connect_host, host_header, tls_server_name, tls_insecure_skip_verify, sync_interval_sec, sync_enabled, dirty, next_sync_at, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES ((SELECT id FROM repos WHERE public_id = ?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT(repo_id, path) DO UPDATE SET
|
ON CONFLICT(repo_id, path) DO UPDATE SET
|
||||||
mode = excluded.mode,
|
mode = excluded.mode,
|
||||||
allow_delete = excluded.allow_delete,
|
allow_delete = excluded.allow_delete,
|
||||||
@@ -77,7 +81,10 @@ func (s *Store) GetRPMRepoDir(repoID string, path string) (models.RPMRepoDir, er
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var item models.RPMRepoDir
|
var item models.RPMRepoDir
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT repo_id, path, mode, allow_delete, remote_url, connect_host, host_header, tls_server_name, tls_insecure_skip_verify, sync_interval_sec, sync_enabled, dirty, next_sync_at, sync_running, sync_status, sync_error, sync_step, sync_total, sync_done, sync_failed, sync_deleted, last_sync_started_at, last_sync_finished_at, last_sync_success_at, last_synced_revision, created_at, updated_at FROM rpm_repo_dirs WHERE repo_id = ? AND path = ?`, repoID, path)
|
row = s.DB.QueryRow(`SELECT r.public_id, d.path, d.mode, d.allow_delete, d.remote_url, d.connect_host, d.host_header, d.tls_server_name, d.tls_insecure_skip_verify, d.sync_interval_sec, d.sync_enabled, d.dirty, d.next_sync_at, d.sync_running, d.sync_status, d.sync_error, d.sync_step, d.sync_total, d.sync_done, d.sync_failed, d.sync_deleted, d.last_sync_started_at, d.last_sync_finished_at, d.last_sync_success_at, d.last_synced_revision, d.created_at, d.updated_at
|
||||||
|
FROM rpm_repo_dirs d
|
||||||
|
JOIN repos r ON r.id = d.repo_id
|
||||||
|
WHERE r.public_id = ? AND d.path = ?`, repoID, path)
|
||||||
err = row.Scan(&item.RepoID, &item.Path, &item.Mode, &item.AllowDelete, &item.RemoteURL, &item.ConnectHost, &item.HostHeader, &item.TLSServerName, &item.TLSInsecureSkipVerify, &item.SyncIntervalSec, &item.SyncEnabled, &item.Dirty, &item.NextSyncAt, &item.SyncRunning, &item.SyncStatus, &item.SyncError, &item.SyncStep, &item.SyncTotal, &item.SyncDone, &item.SyncFailed, &item.SyncDeleted, &item.LastSyncStartedAt, &item.LastSyncFinishedAt, &item.LastSyncSuccessAt, &item.LastSyncedRevision, &item.CreatedAt, &item.UpdatedAt)
|
err = row.Scan(&item.RepoID, &item.Path, &item.Mode, &item.AllowDelete, &item.RemoteURL, &item.ConnectHost, &item.HostHeader, &item.TLSServerName, &item.TLSInsecureSkipVerify, &item.SyncIntervalSec, &item.SyncEnabled, &item.Dirty, &item.NextSyncAt, &item.SyncRunning, &item.SyncStatus, &item.SyncError, &item.SyncStep, &item.SyncTotal, &item.SyncDone, &item.SyncFailed, &item.SyncDeleted, &item.LastSyncStartedAt, &item.LastSyncFinishedAt, &item.LastSyncSuccessAt, &item.LastSyncedRevision, &item.CreatedAt, &item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -94,7 +101,7 @@ func (s *Store) ListDueRPMMirrorTasks(now int64, limit int) ([]models.RPMMirrorT
|
|||||||
limit = 10
|
limit = 10
|
||||||
}
|
}
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT d.repo_id, r.path, d.path, d.remote_url, d.connect_host, d.host_header, d.tls_server_name, d.tls_insecure_skip_verify, d.sync_interval_sec, d.dirty, d.last_synced_revision
|
SELECT r.public_id, r.path, d.path, d.remote_url, d.connect_host, d.host_header, d.tls_server_name, d.tls_insecure_skip_verify, d.sync_interval_sec, d.dirty, d.last_synced_revision
|
||||||
FROM rpm_repo_dirs d
|
FROM rpm_repo_dirs d
|
||||||
JOIN repos r ON r.id = d.repo_id
|
JOIN repos r ON r.id = d.repo_id
|
||||||
WHERE d.mode = 'mirror' AND d.sync_enabled = 1 AND d.sync_running = 0 AND (d.dirty = 1 OR d.next_sync_at <= ? OR d.next_sync_at = 0)
|
WHERE d.mode = 'mirror' AND d.sync_enabled = 1 AND d.sync_running = 0 AND (d.dirty = 1 OR d.next_sync_at <= ? OR d.next_sync_at = 0)
|
||||||
@@ -122,7 +129,7 @@ func (s *Store) TryStartRPMMirrorTask(repoID string, path string, now int64) (bo
|
|||||||
var res sql.Result
|
var res sql.Result
|
||||||
var rows int64
|
var rows int64
|
||||||
var err error
|
var err error
|
||||||
res, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 1, sync_status = 'running', sync_error = '', sync_step = 'start', sync_total = 0, sync_done = 0, sync_failed = 0, sync_deleted = 0, last_sync_started_at = ?, updated_at = ? WHERE repo_id = ? AND path = ? AND mode = 'mirror' AND sync_enabled = 1 AND sync_running = 0`, now, now, repoID, path)
|
res, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 1, sync_status = 'running', sync_error = '', sync_step = 'start', sync_total = 0, sync_done = 0, sync_failed = 0, sync_deleted = 0, last_sync_started_at = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ? AND mode = 'mirror' AND sync_enabled = 1 AND sync_running = 0`, now, now, repoID, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -137,7 +144,7 @@ func (s *Store) UpdateRPMMirrorTaskProgress(repoID string, path string, step str
|
|||||||
var now int64
|
var now int64
|
||||||
var err error
|
var err error
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_step = ?, sync_total = ?, sync_done = ?, sync_failed = ?, sync_deleted = ?, updated_at = ? WHERE repo_id = ? AND path = ?`, step, total, done, failed, deleted, now, repoID, path)
|
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_step = ?, sync_total = ?, sync_done = ?, sync_failed = ?, sync_deleted = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, step, total, done, failed, deleted, now, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +155,7 @@ func (s *Store) FinishRPMMirrorTask(repoID string, path string, success bool, re
|
|||||||
var interval int64
|
var interval int64
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT sync_interval_sec FROM rpm_repo_dirs WHERE repo_id = ? AND path = ?`, repoID, path)
|
row = s.DB.QueryRow(`SELECT sync_interval_sec FROM rpm_repo_dirs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, repoID, path)
|
||||||
err = row.Scan(&interval)
|
err = row.Scan(&interval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -160,14 +167,14 @@ func (s *Store) FinishRPMMirrorTask(repoID string, path string, success bool, re
|
|||||||
nextSync = now + interval
|
nextSync = now + interval
|
||||||
if success {
|
if success {
|
||||||
status = "success"
|
status = "success"
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 0, dirty = 0, next_sync_at = ?, sync_status = ?, sync_error = '', sync_step = 'idle', last_sync_finished_at = ?, last_sync_success_at = ?, last_synced_revision = ?, updated_at = ? WHERE repo_id = ? AND path = ?`, nextSync, status, now, now, revision, now, repoID, path)
|
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 0, dirty = 0, next_sync_at = ?, sync_status = ?, sync_error = '', sync_step = 'idle', last_sync_finished_at = ?, last_sync_success_at = ?, last_synced_revision = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, nextSync, status, now, now, revision, now, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
status = "failed"
|
status = "failed"
|
||||||
if errMsg == "" {
|
if errMsg == "" {
|
||||||
errMsg = "mirror sync failed"
|
errMsg = "mirror sync failed"
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 0, dirty = 1, next_sync_at = ?, sync_status = ?, sync_error = ?, sync_step = 'idle', last_sync_finished_at = ?, updated_at = ? WHERE repo_id = ? AND path = ?`, now+30, status, errMsg, now, now, repoID, path)
|
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_running = 0, dirty = 1, next_sync_at = ?, sync_status = ?, sync_error = ?, sync_step = 'idle', last_sync_finished_at = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, now+30, status, errMsg, now, now, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +182,7 @@ func (s *Store) MarkRPMMirrorTaskDirty(repoID string, path string) error {
|
|||||||
var now int64
|
var now int64
|
||||||
var err error
|
var err error
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET dirty = 1, next_sync_at = ?, updated_at = ? WHERE repo_id = ? AND path = ?`, now, now, repoID, path)
|
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET dirty = 1, next_sync_at = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, now, now, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +190,7 @@ func (s *Store) SetRPMMirrorSyncEnabled(repoID string, path string, enabled bool
|
|||||||
var now int64
|
var now int64
|
||||||
var err error
|
var err error
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_enabled = ?, dirty = CASE WHEN ? THEN 1 ELSE dirty END, next_sync_at = CASE WHEN ? THEN ? ELSE next_sync_at END, updated_at = ? WHERE repo_id = ? AND path = ?`,
|
_, err = s.DB.Exec(`UPDATE rpm_repo_dirs SET sync_enabled = ?, dirty = CASE WHEN ? THEN 1 ELSE dirty END, next_sync_at = CASE WHEN ? THEN ? ELSE next_sync_at END, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`,
|
||||||
enabled, enabled, enabled, now, now, repoID, path)
|
enabled, enabled, enabled, now, now, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -202,7 +209,7 @@ func (s *Store) ListRPMMirrorPaths() ([]models.RPMMirrorTask, error) {
|
|||||||
var item models.RPMMirrorTask
|
var item models.RPMMirrorTask
|
||||||
var err error
|
var err error
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT d.repo_id, r.path, d.path
|
SELECT r.public_id, r.path, d.path
|
||||||
FROM rpm_repo_dirs d
|
FROM rpm_repo_dirs d
|
||||||
JOIN repos r ON r.id = d.repo_id
|
JOIN repos r ON r.id = d.repo_id
|
||||||
WHERE d.mode = 'mirror'`)
|
WHERE d.mode = 'mirror'`)
|
||||||
@@ -228,7 +235,7 @@ func (s *Store) HasRunningRPMMirrorTask(repoID string) (bool, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var count int64
|
var count int64
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT COUNT(1) FROM rpm_repo_dirs WHERE repo_id = ? AND mode = 'mirror' AND sync_running = 1`, repoID)
|
row = s.DB.QueryRow(`SELECT COUNT(1) FROM rpm_repo_dirs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND mode = 'mirror' AND sync_running = 1`, repoID)
|
||||||
err = row.Scan(&count)
|
err = row.Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -243,7 +250,7 @@ func (s *Store) CreateRPMMirrorRun(repoID string, path string, startedAt int64)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`INSERT INTO rpm_mirror_runs (id, repo_id, path, started_at, status) VALUES (?, ?, ?, ?, 'running')`, id, repoID, path, startedAt)
|
_, err = s.DB.Exec(`INSERT INTO rpm_mirror_runs (public_id, repo_id, path, started_at, status) VALUES (?, (SELECT id FROM repos WHERE public_id = ?), ?, ?, 'running')`, id, repoID, path, startedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -252,7 +259,7 @@ func (s *Store) CreateRPMMirrorRun(repoID string, path string, startedAt int64)
|
|||||||
|
|
||||||
func (s *Store) FinishRPMMirrorRun(id string, finishedAt int64, status string, step string, total int64, done int64, failed int64, deleted int64, revision string, errMsg string) error {
|
func (s *Store) FinishRPMMirrorRun(id string, finishedAt int64, status string, step string, total int64, done int64, failed int64, deleted int64, revision string, errMsg string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE rpm_mirror_runs SET finished_at = ?, status = ?, step = ?, total = ?, done = ?, failed = ?, deleted = ?, revision = ?, error = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE rpm_mirror_runs SET finished_at = ?, status = ?, step = ?, total = ?, done = ?, failed = ?, deleted = ?, revision = ?, error = ? WHERE public_id = ?`,
|
||||||
finishedAt, status, step, total, done, failed, deleted, revision, errMsg, id)
|
finishedAt, status, step, total, done, failed, deleted, revision, errMsg, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -265,7 +272,12 @@ func (s *Store) ListRPMMirrorRuns(repoID string, path string, limit int) ([]mode
|
|||||||
if limit <= 0 {
|
if limit <= 0 {
|
||||||
limit = 20
|
limit = 20
|
||||||
}
|
}
|
||||||
rows, err = s.DB.Query(`SELECT id, repo_id, path, started_at, finished_at, status, step, total, done, failed, deleted, revision, error FROM rpm_mirror_runs WHERE repo_id = ? AND path = ? ORDER BY started_at DESC LIMIT ?`, repoID, path, limit)
|
rows, err = s.DB.Query(`SELECT m.public_id, r.public_id, m.path, m.started_at, m.finished_at, m.status, m.step, m.total, m.done, m.failed, m.deleted, m.revision, m.error
|
||||||
|
FROM rpm_mirror_runs m
|
||||||
|
JOIN repos r ON r.id = m.repo_id
|
||||||
|
WHERE r.public_id = ? AND m.path = ?
|
||||||
|
ORDER BY m.started_at DESC
|
||||||
|
LIMIT ?`, repoID, path, limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -288,7 +300,7 @@ func (s *Store) DeleteRPMMirrorRuns(repoID string, path string) (int64, error) {
|
|||||||
var res sql.Result
|
var res sql.Result
|
||||||
var count int64
|
var count int64
|
||||||
var err error
|
var err error
|
||||||
res, err = s.DB.Exec(`DELETE FROM rpm_mirror_runs WHERE repo_id = ? AND path = ?`, repoID, path)
|
res, err = s.DB.Exec(`DELETE FROM rpm_mirror_runs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, repoID, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -313,12 +325,12 @@ func (s *Store) CleanupRPMMirrorRunsRetention(repoID string, path string, keepCo
|
|||||||
cutoff = now - int64(keepDays*24*60*60)
|
cutoff = now - int64(keepDays*24*60*60)
|
||||||
_, err = s.DB.Exec(`
|
_, err = s.DB.Exec(`
|
||||||
DELETE FROM rpm_mirror_runs
|
DELETE FROM rpm_mirror_runs
|
||||||
WHERE repo_id = ?
|
WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?)
|
||||||
AND path = ?
|
AND path = ?
|
||||||
AND started_at < ?
|
AND started_at < ?
|
||||||
AND id NOT IN (
|
AND id NOT IN (
|
||||||
SELECT id FROM rpm_mirror_runs
|
SELECT id FROM rpm_mirror_runs
|
||||||
WHERE repo_id = ? AND path = ?
|
WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?
|
||||||
ORDER BY started_at DESC
|
ORDER BY started_at DESC
|
||||||
LIMIT ?
|
LIMIT ?
|
||||||
)
|
)
|
||||||
@@ -337,7 +349,7 @@ func normalizeRPMRepoMode(mode string) string {
|
|||||||
|
|
||||||
func (s *Store) DeleteRPMRepoDir(repoID string, path string) error {
|
func (s *Store) DeleteRPMRepoDir(repoID string, path string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM rpm_repo_dirs WHERE repo_id = ? AND path = ?`, repoID, path)
|
_, err = s.DB.Exec(`DELETE FROM rpm_repo_dirs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, repoID, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +357,7 @@ func (s *Store) DeleteRPMRepoDirSubtree(repoID string, path string) error {
|
|||||||
var prefix string
|
var prefix string
|
||||||
var err error
|
var err error
|
||||||
prefix = path + "/"
|
prefix = path + "/"
|
||||||
_, err = s.DB.Exec(`DELETE FROM rpm_repo_dirs WHERE repo_id = ? AND (path = ? OR path LIKE (? || '%'))`, repoID, path, prefix)
|
_, err = s.DB.Exec(`DELETE FROM rpm_repo_dirs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND (path = ? OR path LIKE (? || '%'))`, repoID, path, prefix)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,17 +374,17 @@ func (s *Store) MoveRPMRepoDir(repoID string, oldPath string, newPath string) er
|
|||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
oldPrefix = oldPath + "/"
|
oldPrefix = oldPath + "/"
|
||||||
newPrefix = newPath + "/"
|
newPrefix = newPath + "/"
|
||||||
_, err = tx.Exec(`DELETE FROM rpm_mirror_runs WHERE repo_id = ? AND (path = ? OR path LIKE (? || '%'))`, repoID, oldPath, oldPrefix)
|
_, err = tx.Exec(`DELETE FROM rpm_mirror_runs WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND (path = ? OR path LIKE (? || '%'))`, repoID, oldPath, oldPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`UPDATE rpm_repo_dirs SET path = ?, updated_at = ? WHERE repo_id = ? AND path = ?`, newPath, now, repoID, oldPath)
|
_, err = tx.Exec(`UPDATE rpm_repo_dirs SET path = ?, updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path = ?`, newPath, now, repoID, oldPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`UPDATE rpm_repo_dirs SET path = (? || SUBSTR(path, ?)), updated_at = ? WHERE repo_id = ? AND path LIKE (? || '%')`, newPrefix, len(oldPrefix)+1, now, repoID, oldPrefix)
|
_, err = tx.Exec(`UPDATE rpm_repo_dirs SET path = (? || SUBSTR(path, ?)), updated_at = ? WHERE repo_id = (SELECT id FROM repos WHERE public_id = ?) AND path LIKE (? || '%')`, newPrefix, len(oldPrefix)+1, now, repoID, oldPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (s *Store) CreateUser(user models.User, passwordHash string) (models.User,
|
|||||||
user.AuthSource = "db"
|
user.AuthSource = "db"
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`
|
_, err = s.DB.Exec(`
|
||||||
INSERT INTO users (id, username, display_name, email, password_hash, is_admin, disabled, auth_source, created_at, updated_at)
|
INSERT INTO users (public_id, username, display_name, email, password_hash, is_admin, disabled, auth_source, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`, user.ID, user.Username, user.DisplayName, user.Email, passwordHash, user.IsAdmin, user.Disabled, user.AuthSource, now, now)
|
`, user.ID, user.Username, user.DisplayName, user.Email, passwordHash, user.IsAdmin, user.Disabled, user.AuthSource, now, now)
|
||||||
return user, err
|
return user, err
|
||||||
@@ -41,7 +41,7 @@ func (s *Store) UpdateUser(user models.User) error {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
user.UpdatedAt = nowUnix
|
user.UpdatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, updated_at = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, now, user.ID)
|
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, now, user.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, password_hash = ?, updated_at = ? WHERE id = ?`,
|
_, err = tx.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, password_hash = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, passwordHash, now, user.ID)
|
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, passwordHash, now, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
@@ -73,7 +73,7 @@ func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) er
|
|||||||
|
|
||||||
func (s *Store) SetUserPassword(userID, passwordHash string) error {
|
func (s *Store) SetUserPassword(userID, passwordHash string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?`, passwordHash, time.Now().UTC(), userID)
|
_, err = s.DB.Exec(`UPDATE users SET password_hash = ?, updated_at = ? WHERE public_id = ?`, passwordHash, time.Now().UTC(), userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ func (s *Store) GetUserByID(id string) (models.User, error) {
|
|||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, username, display_name, email, is_admin, disabled, auth_source, created_at, updated_at FROM users WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT public_id, username, display_name, email, is_admin, disabled, auth_source, created_at, updated_at FROM users WHERE public_id = ?`, id)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthSource, &created, &updated)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthSource, &created, &updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
@@ -100,7 +100,7 @@ func (s *Store) GetUserByUsername(username string) (models.User, string, error)
|
|||||||
var err error
|
var err error
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
row = s.DB.QueryRow(`SELECT id, username, display_name, email, is_admin, disabled, auth_source, password_hash, created_at, updated_at FROM users WHERE username = ?`, username)
|
row = s.DB.QueryRow(`SELECT public_id, username, display_name, email, is_admin, disabled, auth_source, password_hash, created_at, updated_at FROM users WHERE username = ?`, username)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthSource, &passwordHash, &created, &updated)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthSource, &passwordHash, &created, &updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, passwordHash.String, err
|
return user, passwordHash.String, err
|
||||||
@@ -117,7 +117,7 @@ func (s *Store) ListUsers() ([]models.User, error) {
|
|||||||
var u models.User
|
var u models.User
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
rows, err = s.DB.Query(`SELECT id, username, display_name, email, is_admin, disabled, auth_source, created_at, updated_at FROM users ORDER BY username`)
|
rows, err = s.DB.Query(`SELECT public_id, username, display_name, email, is_admin, disabled, auth_source, created_at, updated_at FROM users ORDER BY username`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ func (s *Store) ListUsers() ([]models.User, error) {
|
|||||||
|
|
||||||
func (s *Store) DeleteUser(id string) error {
|
func (s *Store) DeleteUser(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM users WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM users WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +520,7 @@ func (s *Store) SetUserDisabled(id string, disabled bool) error {
|
|||||||
var err error
|
var err error
|
||||||
var now time.Time
|
var now time.Time
|
||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
_, err = s.DB.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE id = ?`, disabled, now, id)
|
_, err = s.DB.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE public_id = ?`, disabled, now, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +546,8 @@ func (s *Store) CreateAPIKey(userID string, name string, tokenHash string, prefi
|
|||||||
ExpiresAt: expiresAt,
|
ExpiresAt: expiresAt,
|
||||||
Disabled: false,
|
Disabled: false,
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`INSERT INTO api_keys (id, user_id, name, token_hash, token_prefix, created_at, last_used_at, expires_at, disabled) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO api_keys (public_id, user_id, name, token_hash, token_prefix, created_at, last_used_at, expires_at, disabled)
|
||||||
|
VALUES (?, (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
key.ID, key.UserID, key.Name, tokenHash, key.Prefix, key.CreatedAt, key.LastUsedAt, key.ExpiresAt, key.Disabled)
|
key.ID, key.UserID, key.Name, tokenHash, key.Prefix, key.CreatedAt, key.LastUsedAt, key.ExpiresAt, key.Disabled)
|
||||||
return key, err
|
return key, err
|
||||||
}
|
}
|
||||||
@@ -556,7 +557,11 @@ func (s *Store) ListAPIKeys(userID string) ([]models.APIKey, error) {
|
|||||||
var err error
|
var err error
|
||||||
var keys []models.APIKey
|
var keys []models.APIKey
|
||||||
var key models.APIKey
|
var key models.APIKey
|
||||||
rows, err = s.DB.Query(`SELECT id, user_id, name, token_prefix, created_at, last_used_at, expires_at, disabled FROM api_keys WHERE user_id = ? ORDER BY created_at DESC`, userID)
|
rows, err = s.DB.Query(`SELECT k.public_id, u.public_id, k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
||||||
|
FROM api_keys k
|
||||||
|
JOIN users u ON u.id = k.user_id
|
||||||
|
WHERE u.public_id = ?
|
||||||
|
ORDER BY k.created_at DESC`, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -573,25 +578,25 @@ func (s *Store) ListAPIKeys(userID string) ([]models.APIKey, error) {
|
|||||||
|
|
||||||
func (s *Store) DeleteAPIKey(userID string, id string) error {
|
func (s *Store) DeleteAPIKey(userID string, id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM api_keys WHERE id = ? AND user_id = ?`, id, userID)
|
_, err = s.DB.Exec(`DELETE FROM api_keys WHERE public_id = ? AND user_id = (SELECT id FROM users WHERE public_id = ?)`, id, userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) SetAPIKeyDisabled(userID string, id string, disabled bool) error {
|
func (s *Store) SetAPIKeyDisabled(userID string, id string, disabled bool) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE api_keys SET disabled = ? WHERE id = ? AND user_id = ?`, disabled, id, userID)
|
_, err = s.DB.Exec(`UPDATE api_keys SET disabled = ? WHERE public_id = ? AND user_id = (SELECT id FROM users WHERE public_id = ?)`, disabled, id, userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteAPIKeyByID(id string) error {
|
func (s *Store) DeleteAPIKeyByID(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM api_keys WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM api_keys WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) SetAPIKeyDisabledByID(id string, disabled bool) error {
|
func (s *Store) SetAPIKeyDisabledByID(id string, disabled bool) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE api_keys SET disabled = ? WHERE id = ?`, disabled, id)
|
_, err = s.DB.Exec(`UPDATE api_keys SET disabled = ? WHERE public_id = ?`, disabled, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,11 +612,11 @@ func (s *Store) ListAPIKeysAdmin(userID string, query string) ([]models.AdminAPI
|
|||||||
if userID != "" && query != "" {
|
if userID != "" && query != "" {
|
||||||
sqlQuery = `
|
sqlQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
k.id, k.user_id, u.username, u.display_name, u.email,
|
k.public_id, u.public_id, u.username, u.display_name, u.email,
|
||||||
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
JOIN users u ON u.id = k.user_id
|
JOIN users u ON u.id = k.user_id
|
||||||
WHERE k.user_id = ?
|
WHERE u.public_id = ?
|
||||||
AND (k.name LIKE ? OR k.token_prefix LIKE ? OR u.username LIKE ? OR u.display_name LIKE ? OR u.email LIKE ?)
|
AND (k.name LIKE ? OR k.token_prefix LIKE ? OR u.username LIKE ? OR u.display_name LIKE ? OR u.email LIKE ?)
|
||||||
ORDER BY k.created_at DESC
|
ORDER BY k.created_at DESC
|
||||||
`
|
`
|
||||||
@@ -619,18 +624,18 @@ func (s *Store) ListAPIKeysAdmin(userID string, query string) ([]models.AdminAPI
|
|||||||
} else if userID != "" {
|
} else if userID != "" {
|
||||||
sqlQuery = `
|
sqlQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
k.id, k.user_id, u.username, u.display_name, u.email,
|
k.public_id, u.public_id, u.username, u.display_name, u.email,
|
||||||
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
JOIN users u ON u.id = k.user_id
|
JOIN users u ON u.id = k.user_id
|
||||||
WHERE k.user_id = ?
|
WHERE u.public_id = ?
|
||||||
ORDER BY k.created_at DESC
|
ORDER BY k.created_at DESC
|
||||||
`
|
`
|
||||||
rows, err = s.DB.Query(sqlQuery, userID)
|
rows, err = s.DB.Query(sqlQuery, userID)
|
||||||
} else if query != "" {
|
} else if query != "" {
|
||||||
sqlQuery = `
|
sqlQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
k.id, k.user_id, u.username, u.display_name, u.email,
|
k.public_id, u.public_id, u.username, u.display_name, u.email,
|
||||||
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
JOIN users u ON u.id = k.user_id
|
JOIN users u ON u.id = k.user_id
|
||||||
@@ -641,7 +646,7 @@ func (s *Store) ListAPIKeysAdmin(userID string, query string) ([]models.AdminAPI
|
|||||||
} else {
|
} else {
|
||||||
sqlQuery = `
|
sqlQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
k.id, k.user_id, u.username, u.display_name, u.email,
|
k.public_id, u.public_id, u.username, u.display_name, u.email,
|
||||||
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
JOIN users u ON u.id = k.user_id
|
JOIN users u ON u.id = k.user_id
|
||||||
@@ -680,7 +685,7 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
var keyID string
|
var keyID int64
|
||||||
var now time.Time
|
var now time.Time
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
var err error
|
var err error
|
||||||
@@ -688,7 +693,7 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
currentUnix = now.Unix()
|
currentUnix = now.Unix()
|
||||||
row = s.DB.QueryRow(`
|
row = s.DB.QueryRow(`
|
||||||
SELECT u.id, u.username, u.display_name, u.email, u.is_admin, u.disabled, u.auth_source, u.created_at, u.updated_at, k.id
|
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, u.auth_source, u.created_at, u.updated_at, k.id
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
JOIN users u ON u.id = k.user_id
|
JOIN users u ON u.id = k.user_id
|
||||||
WHERE k.token_hash = ?
|
WHERE k.token_hash = ?
|
||||||
@@ -711,7 +716,8 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
|||||||
|
|
||||||
func (s *Store) CreateSession(userID, token string, expiresAt time.Time) error {
|
func (s *Store) CreateSession(userID, token string, expiresAt time.Time) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`INSERT INTO sessions (id, user_id, token, expires_at, created_at) VALUES (?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO sessions (id, user_id, token, expires_at, created_at)
|
||||||
|
VALUES (?, (SELECT id FROM users WHERE public_id = ?), ?, ?, ?)`,
|
||||||
mustID(), userID, token, expiresAt, time.Now().UTC())
|
mustID(), userID, token, expiresAt, time.Now().UTC())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -730,7 +736,7 @@ func (s *Store) GetSessionUser(token string) (models.User, time.Time, error) {
|
|||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
row = s.DB.QueryRow(`
|
row = s.DB.QueryRow(`
|
||||||
SELECT u.id, u.username, u.display_name, u.email, u.is_admin, u.disabled, u.auth_source, u.created_at, u.updated_at, s.expires_at
|
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, u.auth_source, u.created_at, u.updated_at, s.expires_at
|
||||||
FROM sessions s JOIN users u ON u.id = s.user_id
|
FROM sessions s JOIN users u ON u.id = s.user_id
|
||||||
WHERE s.token = ? AND u.disabled = 0
|
WHERE s.token = ? AND u.disabled = 0
|
||||||
`, token)
|
`, token)
|
||||||
@@ -770,8 +776,8 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
if project.HomePage == "" {
|
if project.HomePage == "" {
|
||||||
project.HomePage = "info"
|
project.HomePage = "info"
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`INSERT INTO projects (id, slug, name, description, home_page, created_by, updated_by, created_at, updated_at, created_at_unix, updated_at_unix)
|
_, err = tx.Exec(`INSERT INTO projects (public_id, slug, name, description, home_page, created_by, updated_by, created_at, updated_at, created_at_unix, updated_at_unix)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?)`,
|
||||||
project.ID,
|
project.ID,
|
||||||
project.Slug,
|
project.Slug,
|
||||||
project.Name,
|
project.Name,
|
||||||
@@ -788,7 +794,8 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
return project, err
|
return project, err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`INSERT INTO project_members (project_id, user_id, role, created_at) VALUES (?, ?, ?, ?)`,
|
_, err = tx.Exec(`INSERT INTO project_members (project_id, user_id, role, created_at)
|
||||||
|
VALUES ((SELECT id FROM projects WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)`,
|
||||||
project.ID, project.CreatedBy, "admin", now)
|
project.ID, project.CreatedBy, "admin", now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tx.Rollback()
|
_ = tx.Rollback()
|
||||||
@@ -807,7 +814,7 @@ func (s *Store) UpdateProject(project models.Project) error {
|
|||||||
if project.HomePage == "" {
|
if project.HomePage == "" {
|
||||||
project.HomePage = "info"
|
project.HomePage = "info"
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`UPDATE projects SET slug = ?, name = ?, description = ?, home_page = ?, updated_at = ?, updated_by = ?, updated_at_unix = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE projects SET slug = ?, name = ?, description = ?, home_page = ?, updated_at = ?, updated_by = (SELECT id FROM users WHERE public_id = ?), updated_at_unix = ? WHERE public_id = ?`,
|
||||||
project.Slug,
|
project.Slug,
|
||||||
project.Name,
|
project.Name,
|
||||||
project.Description,
|
project.Description,
|
||||||
@@ -824,14 +831,14 @@ func (s *Store) GetProject(id string) (models.Project, error) {
|
|||||||
var project models.Project
|
var project models.Project
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
row = s.DB.QueryRow(`
|
row = s.DB.QueryRow(`
|
||||||
SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
WHERE p.id = ?
|
WHERE p.public_id = ?
|
||||||
`, id)
|
`, id)
|
||||||
return project, row.Scan(
|
return project, row.Scan(
|
||||||
&project.ID,
|
&project.ID,
|
||||||
@@ -853,8 +860,8 @@ func (s *Store) GetProjectBySlug(slug string) (models.Project, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`
|
row = s.DB.QueryRow(`
|
||||||
SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
@@ -887,8 +894,8 @@ func (s *Store) ListProjects() ([]models.Project, error) {
|
|||||||
var projects []models.Project
|
var projects []models.Project
|
||||||
var p models.Project
|
var p models.Project
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
@@ -928,15 +935,15 @@ func (s *Store) ListProjectsForUser(userID string) ([]models.Project, error) {
|
|||||||
var projects []models.Project
|
var projects []models.Project
|
||||||
var p models.Project
|
var p models.Project
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
JOIN project_members m ON m.project_id = p.id
|
JOIN project_members m ON m.project_id = p.id
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
WHERE m.user_id = ?
|
WHERE m.user_id = (SELECT id FROM users WHERE public_id = ?)
|
||||||
ORDER BY p.name
|
ORDER BY p.name
|
||||||
`, userID)
|
`, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -978,8 +985,8 @@ func (s *Store) ListProjectsFiltered(limit int, offset int, query string) ([]mod
|
|||||||
}
|
}
|
||||||
if query == "" {
|
if query == "" {
|
||||||
rows, err = s.DB.Query(
|
rows, err = s.DB.Query(
|
||||||
`SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
@@ -991,8 +998,8 @@ func (s *Store) ListProjectsFiltered(limit int, offset int, query string) ([]mod
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
rows, err = s.DB.Query(
|
rows, err = s.DB.Query(
|
||||||
`SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
@@ -1045,15 +1052,15 @@ func (s *Store) ListProjectsFilteredForUser(userID string, limit int, offset int
|
|||||||
}
|
}
|
||||||
if query == "" {
|
if query == "" {
|
||||||
rows, err = s.DB.Query(
|
rows, err = s.DB.Query(
|
||||||
`SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
JOIN project_members m ON m.project_id = p.id
|
JOIN project_members m ON m.project_id = p.id
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
WHERE m.user_id = ?
|
WHERE m.user_id = (SELECT id FROM users WHERE public_id = ?)
|
||||||
ORDER BY p.name LIMIT ? OFFSET ?`,
|
ORDER BY p.name LIMIT ? OFFSET ?`,
|
||||||
userID,
|
userID,
|
||||||
limit,
|
limit,
|
||||||
@@ -1061,15 +1068,15 @@ func (s *Store) ListProjectsFilteredForUser(userID string, limit int, offset int
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
rows, err = s.DB.Query(
|
rows, err = s.DB.Query(
|
||||||
`SELECT p.id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
p.created_by, p.updated_by,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at_unix, p.updated_at_unix
|
||||||
FROM projects p
|
FROM projects p
|
||||||
JOIN project_members m ON m.project_id = p.id
|
JOIN project_members m ON m.project_id = p.id
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
WHERE m.user_id = ? AND (p.name LIKE ? OR p.slug LIKE ?)
|
WHERE m.user_id = (SELECT id FROM users WHERE public_id = ?) AND (p.name LIKE ? OR p.slug LIKE ?)
|
||||||
ORDER BY p.name LIMIT ? OFFSET ?`,
|
ORDER BY p.name LIMIT ? OFFSET ?`,
|
||||||
userID,
|
userID,
|
||||||
"%"+query+"%",
|
"%"+query+"%",
|
||||||
@@ -1106,7 +1113,7 @@ func (s *Store) ListProjectsFilteredForUser(userID string, limit int, offset int
|
|||||||
|
|
||||||
func (s *Store) DeleteProject(id string) error {
|
func (s *Store) DeleteProject(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM projects WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM projects WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,20 +1123,25 @@ func (s *Store) AddProjectMember(projectID, userID, role string) (models.Project
|
|||||||
var now time.Time
|
var now time.Time
|
||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
member = models.ProjectMember{ProjectID: projectID, UserID: userID, Role: role, CreatedAt: now.Unix()}
|
member = models.ProjectMember{ProjectID: projectID, UserID: userID, Role: role, CreatedAt: now.Unix()}
|
||||||
_, err = s.DB.Exec(`INSERT INTO project_members (project_id, user_id, role, created_at) VALUES (?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO project_members (project_id, user_id, role, created_at)
|
||||||
|
VALUES ((SELECT id FROM projects WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)`,
|
||||||
member.ProjectID, member.UserID, member.Role, now)
|
member.ProjectID, member.UserID, member.Role, now)
|
||||||
return member, err
|
return member, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateProjectMemberRole(projectID, userID, role string) error {
|
func (s *Store) UpdateProjectMemberRole(projectID, userID, role string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE project_members SET role = ? WHERE project_id = ? AND user_id = ?`, role, projectID, userID)
|
_, err = s.DB.Exec(`UPDATE project_members SET role = ?
|
||||||
|
WHERE project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND user_id = (SELECT id FROM users WHERE public_id = ?)`, role, projectID, userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) RemoveProjectMember(projectID, userID string) error {
|
func (s *Store) RemoveProjectMember(projectID, userID string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM project_members WHERE project_id = ? AND user_id = ?`, projectID, userID)
|
_, err = s.DB.Exec(`DELETE FROM project_members
|
||||||
|
WHERE project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND user_id = (SELECT id FROM users WHERE public_id = ?)`, projectID, userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1139,7 +1151,12 @@ func (s *Store) ListProjectMembers(projectID string) ([]models.ProjectMember, er
|
|||||||
var members []models.ProjectMember
|
var members []models.ProjectMember
|
||||||
var m models.ProjectMember
|
var m models.ProjectMember
|
||||||
var created time.Time
|
var created time.Time
|
||||||
rows, err = s.DB.Query(`SELECT project_id, user_id, role, created_at FROM project_members WHERE project_id = ? ORDER BY role`, projectID)
|
rows, err = s.DB.Query(`SELECT p.public_id, u.public_id, m.role, m.created_at
|
||||||
|
FROM project_members m
|
||||||
|
JOIN projects p ON p.id = m.project_id
|
||||||
|
JOIN users u ON u.id = m.user_id
|
||||||
|
WHERE m.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY m.role`, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1159,7 +1176,9 @@ func (s *Store) GetProjectMemberRole(projectID, userID string) (string, error) {
|
|||||||
var role string
|
var role string
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT role FROM project_members WHERE project_id = ? AND user_id = ?`, projectID, userID)
|
row = s.DB.QueryRow(`SELECT role FROM project_members
|
||||||
|
WHERE project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND user_id = (SELECT id FROM users WHERE public_id = ?)`, projectID, userID)
|
||||||
err = row.Scan(&role)
|
err = row.Scan(&role)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -1182,7 +1201,8 @@ func (s *Store) CreateRepo(repo models.Repo) (models.Repo, error) {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
repo.CreatedAt = nowUnix
|
repo.CreatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`INSERT INTO repos (id, project_id, name, type, path, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO repos (public_id, project_id, name, type, path, created_by, created_at)
|
||||||
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
repo.ID, repo.ProjectID, repo.Name, repo.Type, repo.Path, repo.CreatedBy, now)
|
repo.ID, repo.ProjectID, repo.Name, repo.Type, repo.Path, repo.CreatedBy, now)
|
||||||
return repo, err
|
return repo, err
|
||||||
}
|
}
|
||||||
@@ -1191,7 +1211,9 @@ func (s *Store) RepoNameExists(projectID string, name string, repoType string) (
|
|||||||
var count int
|
var count int
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT COUNT(1) FROM repos WHERE project_id = ? AND name = ? AND type = ?`, projectID, name, repoType)
|
row = s.DB.QueryRow(`SELECT COUNT(1) FROM repos
|
||||||
|
WHERE project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND name = ? AND type = ?`, projectID, name, repoType)
|
||||||
err = row.Scan(&count)
|
err = row.Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -1204,7 +1226,11 @@ func (s *Store) GetRepo(id string) (models.Repo, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, project_id, name, type, path, created_by, created_at FROM repos WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
|
FROM repos r
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE r.public_id = ?`, id)
|
||||||
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, err
|
return repo, err
|
||||||
@@ -1213,12 +1239,33 @@ func (s *Store) GetRepo(id string) (models.Repo, error) {
|
|||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Store) GetRepoStorageIDs(id string) (int64, int64, error) {
|
||||||
|
var row *sql.Row
|
||||||
|
var projectID int64
|
||||||
|
var repoID int64
|
||||||
|
var err error
|
||||||
|
row = s.DB.QueryRow(`SELECT p.id, r.id
|
||||||
|
FROM repos r
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
WHERE r.public_id = ?`, id)
|
||||||
|
err = row.Scan(&projectID, &repoID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
return projectID, repoID, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Store) GetRepoByProjectNameType(projectID string, name string, repoType string) (models.Repo, error) {
|
func (s *Store) GetRepoByProjectNameType(projectID string, name string, repoType string) (models.Repo, error) {
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
var created time.Time
|
var created time.Time
|
||||||
row = s.DB.QueryRow(`SELECT id, project_id, name, type, path, created_by, created_at FROM repos WHERE project_id = ? AND name = ? AND type = ?`,
|
row = s.DB.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
|
FROM repos r
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE r.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND r.name = ? AND r.type = ?`,
|
||||||
projectID, name, repoType)
|
projectID, name, repoType)
|
||||||
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1236,15 +1283,20 @@ func (s *Store) ListRepos(projectID string) ([]models.Repo, error) {
|
|||||||
var isForeign int
|
var isForeign int
|
||||||
var created time.Time
|
var created time.Time
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at, 0 AS is_foreign
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at, 0 AS is_foreign
|
||||||
FROM repos
|
|
||||||
WHERE project_id = ?
|
|
||||||
UNION ALL
|
|
||||||
SELECT r.id, r.project_id, r.name, r.type, r.path, r.created_by, r.created_at, 1 AS is_foreign
|
|
||||||
FROM repos r
|
FROM repos r
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE r.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
UNION ALL
|
||||||
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at, 1 AS is_foreign
|
||||||
|
FROM repos r
|
||||||
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
JOIN users u ON u.id = r.created_by
|
||||||
JOIN project_repos pr ON pr.repo_id = r.id
|
JOIN project_repos pr ON pr.repo_id = r.id
|
||||||
WHERE pr.project_id = ? AND r.project_id <> ?
|
WHERE pr.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
ORDER BY name
|
AND r.project_id <> (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY 3
|
||||||
`, projectID, projectID, projectID)
|
`, projectID, projectID, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1269,10 +1321,12 @@ func (s *Store) ListReposOwned(projectID string) ([]models.Repo, error) {
|
|||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
var created time.Time
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos
|
FROM repos r
|
||||||
WHERE project_id = ?
|
JOIN projects p ON p.id = r.project_id
|
||||||
ORDER BY name
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE r.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY r.name
|
||||||
`, projectID)
|
`, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1296,9 +1350,11 @@ func (s *Store) ListAllRepos() ([]models.Repo, error) {
|
|||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
var created time.Time
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos
|
FROM repos r
|
||||||
ORDER BY name
|
JOIN projects p ON p.id = r.project_id
|
||||||
|
JOIN users u ON u.id = r.created_by
|
||||||
|
ORDER BY r.name
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1324,6 +1380,7 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
|||||||
var placeholders []string
|
var placeholders []string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
var i int
|
var i int
|
||||||
|
var selected []interface{}
|
||||||
if len(projectIDs) == 0 {
|
if len(projectIDs) == 0 {
|
||||||
return []models.Repo{}, nil
|
return []models.Repo{}, nil
|
||||||
}
|
}
|
||||||
@@ -1331,13 +1388,19 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
|||||||
args = make([]interface{}, len(projectIDs))
|
args = make([]interface{}, len(projectIDs))
|
||||||
for i = 0; i < len(projectIDs); i++ {
|
for i = 0; i < len(projectIDs); i++ {
|
||||||
placeholders[i] = "?"
|
placeholders[i] = "?"
|
||||||
args[i] = projectIDs[i]
|
selected = append(selected, projectIDs[i])
|
||||||
|
}
|
||||||
|
args = make([]interface{}, len(selected))
|
||||||
|
for i = 0; i < len(selected); i++ {
|
||||||
|
args[i] = selected[i]
|
||||||
}
|
}
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos
|
FROM repos r
|
||||||
WHERE project_id IN (`+strings.Join(placeholders, ",")+`)
|
JOIN projects p ON p.id = r.project_id
|
||||||
ORDER BY name
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE p.public_id IN (`+strings.Join(placeholders, ",")+`)
|
||||||
|
ORDER BY r.name
|
||||||
`, args...)
|
`, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1359,7 +1422,10 @@ func (s *Store) ListProjectIDsForUser(userID string) ([]string, error) {
|
|||||||
var err error
|
var err error
|
||||||
var ids []string
|
var ids []string
|
||||||
var id string
|
var id string
|
||||||
rows, err = s.DB.Query(`SELECT project_id FROM project_members WHERE user_id = ?`, userID)
|
rows, err = s.DB.Query(`SELECT p.public_id
|
||||||
|
FROM project_members m
|
||||||
|
JOIN projects p ON p.id = m.project_id
|
||||||
|
WHERE m.user_id = (SELECT id FROM users WHERE public_id = ?)`, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1376,26 +1442,29 @@ func (s *Store) ListProjectIDsForUser(userID string) ([]string, error) {
|
|||||||
|
|
||||||
func (s *Store) UpdateRepo(repo models.Repo) error {
|
func (s *Store) UpdateRepo(repo models.Repo) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`UPDATE repos SET name = ?, path = ? WHERE id = ?`, repo.Name, repo.Path, repo.ID)
|
_, err = s.DB.Exec(`UPDATE repos SET name = ?, path = ? WHERE public_id = ?`, repo.Name, repo.Path, repo.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteRepo(id string) error {
|
func (s *Store) DeleteRepo(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM repos WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM repos WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) AttachRepoToProject(projectID string, repoID string) error {
|
func (s *Store) AttachRepoToProject(projectID string, repoID string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`INSERT INTO project_repos (project_id, repo_id, created_at) VALUES (?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO project_repos (project_id, repo_id, created_at)
|
||||||
|
VALUES ((SELECT id FROM projects WHERE public_id = ?), (SELECT id FROM repos WHERE public_id = ?), ?)`,
|
||||||
projectID, repoID, time.Now().UTC())
|
projectID, repoID, time.Now().UTC())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DetachRepoFromProject(projectID string, repoID string) error {
|
func (s *Store) DetachRepoFromProject(projectID string, repoID string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM project_repos WHERE project_id = ? AND repo_id = ?`, projectID, repoID)
|
_, err = s.DB.Exec(`DELETE FROM project_repos
|
||||||
|
WHERE project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
AND repo_id = (SELECT id FROM repos WHERE public_id = ?)`, projectID, repoID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1405,9 +1474,12 @@ func (s *Store) GetRepoProjectIDs(repoID string) ([]string, error) {
|
|||||||
var ids []string
|
var ids []string
|
||||||
var id string
|
var id string
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT project_id FROM repos WHERE id = ?
|
SELECT p.public_id FROM repos r JOIN projects p ON p.id = r.project_id WHERE r.public_id = ?
|
||||||
UNION
|
UNION
|
||||||
SELECT project_id FROM project_repos WHERE repo_id = ?
|
SELECT p.public_id
|
||||||
|
FROM project_repos pr
|
||||||
|
JOIN projects p ON p.id = pr.project_id
|
||||||
|
WHERE pr.repo_id = (SELECT id FROM repos WHERE public_id = ?)
|
||||||
`, repoID, repoID)
|
`, repoID, repoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -1437,20 +1509,35 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
|||||||
}
|
}
|
||||||
if query == "" {
|
if query == "" {
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos
|
FROM repos r
|
||||||
WHERE project_id <> ? AND id NOT IN (SELECT repo_id FROM project_repos WHERE project_id = ?)
|
JOIN projects p ON p.id = r.project_id
|
||||||
ORDER BY name
|
JOIN users u ON u.id = r.created_by
|
||||||
|
WHERE p.public_id <> ?
|
||||||
|
AND r.id NOT IN (
|
||||||
|
SELECT pr.repo_id
|
||||||
|
FROM project_repos pr
|
||||||
|
JOIN projects px ON px.id = pr.project_id
|
||||||
|
WHERE px.public_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY r.name
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
`, projectID, projectID, limit, offset)
|
`, projectID, projectID, limit, offset)
|
||||||
} else {
|
} else {
|
||||||
rows, err = s.DB.Query(`
|
rows, err = s.DB.Query(`
|
||||||
SELECT id, project_id, name, type, path, created_by, created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos
|
FROM repos r
|
||||||
WHERE project_id <> ?
|
JOIN projects p ON p.id = r.project_id
|
||||||
AND id NOT IN (SELECT repo_id FROM project_repos WHERE project_id = ?)
|
JOIN users u ON u.id = r.created_by
|
||||||
AND name LIKE ?
|
WHERE p.public_id <> ?
|
||||||
ORDER BY name
|
AND r.id NOT IN (
|
||||||
|
SELECT pr.repo_id
|
||||||
|
FROM project_repos pr
|
||||||
|
JOIN projects px ON px.id = pr.project_id
|
||||||
|
WHERE px.public_id = ?
|
||||||
|
)
|
||||||
|
AND r.name LIKE ?
|
||||||
|
ORDER BY r.name
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
`, projectID, projectID, "%"+query+"%", limit, offset)
|
`, projectID, projectID, "%"+query+"%", limit, offset)
|
||||||
}
|
}
|
||||||
@@ -1490,9 +1577,9 @@ func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
|||||||
issue.Status = "open"
|
issue.Status = "open"
|
||||||
}
|
}
|
||||||
_, err = s.DB.Exec(`
|
_, err = s.DB.Exec(`
|
||||||
INSERT INTO issues (id, project_id, title, body, status, created_by, assignee_id, created_at, updated_at)
|
INSERT INTO issues (public_id, project_id, title, body, status, created_by, assignee_id, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)
|
||||||
`, issue.ID, issue.ProjectID, issue.Title, issue.Body, issue.Status, issue.CreatedBy, nullIfEmpty(issue.AssigneeID), now, now)
|
`, issue.ID, issue.ProjectID, issue.Title, issue.Body, issue.Status, issue.CreatedBy, issue.AssigneeID, now, now)
|
||||||
return issue, err
|
return issue, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1503,8 +1590,8 @@ func (s *Store) UpdateIssue(issue models.Issue) error {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
issue.UpdatedAt = nowUnix
|
issue.UpdatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`UPDATE issues SET title = ?, body = ?, status = ?, assignee_id = ?, updated_at = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE issues SET title = ?, body = ?, status = ?, assignee_id = (SELECT id FROM users WHERE public_id = ?), updated_at = ? WHERE public_id = ?`,
|
||||||
issue.Title, issue.Body, issue.Status, nullIfEmpty(issue.AssigneeID), now, issue.ID)
|
issue.Title, issue.Body, issue.Status, issue.AssigneeID, now, issue.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1514,7 +1601,12 @@ func (s *Store) GetIssue(id string) (models.Issue, error) {
|
|||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, project_id, title, body, status, created_by, COALESCE(assignee_id, ''), created_at, updated_at FROM issues WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
||||||
|
FROM issues i
|
||||||
|
JOIN projects p ON p.id = i.project_id
|
||||||
|
JOIN users cu ON cu.id = i.created_by
|
||||||
|
LEFT JOIN users au ON au.id = i.assignee_id
|
||||||
|
WHERE i.public_id = ?`, id)
|
||||||
err = row.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &created, &updated)
|
err = row.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &created, &updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return issue, err
|
return issue, err
|
||||||
@@ -1531,7 +1623,13 @@ func (s *Store) ListIssues(projectID string) ([]models.Issue, error) {
|
|||||||
var issue models.Issue
|
var issue models.Issue
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
rows, err = s.DB.Query(`SELECT id, project_id, title, body, status, created_by, COALESCE(assignee_id, ''), created_at, updated_at FROM issues WHERE project_id = ? ORDER BY created_at DESC`, projectID)
|
rows, err = s.DB.Query(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
||||||
|
FROM issues i
|
||||||
|
JOIN projects p ON p.id = i.project_id
|
||||||
|
JOIN users cu ON cu.id = i.created_by
|
||||||
|
LEFT JOIN users au ON au.id = i.assignee_id
|
||||||
|
WHERE i.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY i.created_at DESC`, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1563,7 +1661,8 @@ func (s *Store) AddIssueComment(comment models.IssueComment) (models.IssueCommen
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
comment.CreatedAt = nowUnix
|
comment.CreatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`INSERT INTO issue_comments (id, issue_id, body, created_by, created_at) VALUES (?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO issue_comments (public_id, issue_id, body, created_by, created_at)
|
||||||
|
VALUES (?, (SELECT id FROM issues WHERE public_id = ?), ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, now)
|
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, now)
|
||||||
return comment, err
|
return comment, err
|
||||||
}
|
}
|
||||||
@@ -1583,7 +1682,8 @@ func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
page.UpdatedAt = nowUnix
|
page.UpdatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`INSERT INTO wiki_pages (id, project_id, title, slug, body, created_by, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO wiki_pages (public_id, project_id, title, slug, body, created_by, updated_at)
|
||||||
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
page.ID, page.ProjectID, page.Title, page.Slug, page.Body, page.CreatedBy, now)
|
page.ID, page.ProjectID, page.Title, page.Slug, page.Body, page.CreatedBy, now)
|
||||||
return page, err
|
return page, err
|
||||||
}
|
}
|
||||||
@@ -1595,7 +1695,7 @@ func (s *Store) UpdateWikiPage(page models.WikiPage) error {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
page.UpdatedAt = nowUnix
|
page.UpdatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`UPDATE wiki_pages SET title = ?, body = ?, updated_at = ? WHERE id = ?`, page.Title, page.Body, now, page.ID)
|
_, err = s.DB.Exec(`UPDATE wiki_pages SET title = ?, body = ?, updated_at = ? WHERE public_id = ?`, page.Title, page.Body, now, page.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1605,7 +1705,12 @@ func (s *Store) ListWikiPages(projectID string) ([]models.WikiPage, error) {
|
|||||||
var pages []models.WikiPage
|
var pages []models.WikiPage
|
||||||
var page models.WikiPage
|
var page models.WikiPage
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
rows, err = s.DB.Query(`SELECT id, project_id, title, slug, body, created_by, updated_at FROM wiki_pages WHERE project_id = ? ORDER BY title`, projectID)
|
rows, err = s.DB.Query(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
||||||
|
FROM wiki_pages w
|
||||||
|
JOIN projects p ON p.id = w.project_id
|
||||||
|
JOIN users u ON u.id = w.created_by
|
||||||
|
WHERE w.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY w.title`, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1626,7 +1731,11 @@ func (s *Store) GetWikiPage(id string) (models.WikiPage, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var updated time.Time
|
var updated time.Time
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, project_id, title, slug, body, created_by, updated_at FROM wiki_pages WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
||||||
|
FROM wiki_pages w
|
||||||
|
JOIN projects p ON p.id = w.project_id
|
||||||
|
JOIN users u ON u.id = w.created_by
|
||||||
|
WHERE w.public_id = ?`, id)
|
||||||
err = row.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &updated)
|
err = row.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return page, err
|
return page, err
|
||||||
@@ -1650,7 +1759,8 @@ func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
|||||||
now = time.Now().UTC()
|
now = time.Now().UTC()
|
||||||
nowUnix = now.Unix()
|
nowUnix = now.Unix()
|
||||||
upload.CreatedAt = nowUnix
|
upload.CreatedAt = nowUnix
|
||||||
_, err = s.DB.Exec(`INSERT INTO uploads (id, project_id, filename, content_type, size, storage_path, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO uploads (public_id, project_id, filename, content_type, size, storage_path, created_by, created_at)
|
||||||
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
upload.ID, upload.ProjectID, upload.Filename, upload.ContentType, upload.Size, upload.StoragePath, upload.CreatedBy, now)
|
upload.ID, upload.ProjectID, upload.Filename, upload.ContentType, upload.Size, upload.StoragePath, upload.CreatedBy, now)
|
||||||
return upload, err
|
return upload, err
|
||||||
}
|
}
|
||||||
@@ -1660,7 +1770,11 @@ func (s *Store) GetUpload(id string) (models.Upload, error) {
|
|||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
var created time.Time
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, project_id, filename, content_type, size, storage_path, created_by, created_at FROM uploads WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
||||||
|
FROM uploads up
|
||||||
|
JOIN projects p ON p.id = up.project_id
|
||||||
|
JOIN users u ON u.id = up.created_by
|
||||||
|
WHERE up.public_id = ?`, id)
|
||||||
err = row.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &created)
|
err = row.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &created)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return upload, err
|
return upload, err
|
||||||
@@ -1675,7 +1789,12 @@ func (s *Store) ListUploads(projectID string) ([]models.Upload, error) {
|
|||||||
var uploads []models.Upload
|
var uploads []models.Upload
|
||||||
var upload models.Upload
|
var upload models.Upload
|
||||||
var created time.Time
|
var created time.Time
|
||||||
rows, err = s.DB.Query(`SELECT id, project_id, filename, content_type, size, storage_path, created_by, created_at FROM uploads WHERE project_id = ? ORDER BY created_at DESC`, projectID)
|
rows, err = s.DB.Query(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
||||||
|
FROM uploads up
|
||||||
|
JOIN projects p ON p.id = up.project_id
|
||||||
|
JOIN users u ON u.id = up.created_by
|
||||||
|
WHERE up.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
|
ORDER BY up.created_at DESC`, projectID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func (s *Store) ListTLSListeners() ([]models.TLSListener, error) {
|
|||||||
var httpAddrs string
|
var httpAddrs string
|
||||||
var httpsAddrs string
|
var httpsAddrs string
|
||||||
var certAllowlist string
|
var certAllowlist string
|
||||||
rows, err = s.DB.Query(`SELECT id, name, enabled, http_addrs, https_addrs, auth_policy, apply_policy_api, apply_policy_git, apply_policy_rpm, apply_policy_v2, client_cert_allowlist, tls_server_cert_source, tls_cert_file, tls_key_file, tls_pki_server_cert_id, tls_client_auth, tls_client_ca_file, tls_pki_client_ca_id, tls_min_version, created_at, updated_at FROM tls_listeners ORDER BY name`)
|
rows, err = s.DB.Query(`SELECT l.public_id, l.name, l.enabled, l.http_addrs, l.https_addrs, l.auth_policy, l.apply_policy_api, l.apply_policy_git, l.apply_policy_rpm, l.apply_policy_v2, l.client_cert_allowlist, l.tls_server_cert_source, l.tls_cert_file, l.tls_key_file, l.tls_pki_server_cert_id, l.tls_client_auth, l.tls_client_ca_file, l.tls_pki_client_ca_id, l.tls_min_version, l.created_at, l.updated_at FROM tls_listeners l ORDER BY l.name`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func (s *Store) GetTLSListener(id string) (models.TLSListener, error) {
|
|||||||
var httpsAddrs string
|
var httpsAddrs string
|
||||||
var certAllowlist string
|
var certAllowlist string
|
||||||
var err error
|
var err error
|
||||||
row = s.DB.QueryRow(`SELECT id, name, enabled, http_addrs, https_addrs, auth_policy, apply_policy_api, apply_policy_git, apply_policy_rpm, apply_policy_v2, client_cert_allowlist, tls_server_cert_source, tls_cert_file, tls_key_file, tls_pki_server_cert_id, tls_client_auth, tls_client_ca_file, tls_pki_client_ca_id, tls_min_version, created_at, updated_at FROM tls_listeners WHERE id = ?`, id)
|
row = s.DB.QueryRow(`SELECT l.public_id, l.name, l.enabled, l.http_addrs, l.https_addrs, l.auth_policy, l.apply_policy_api, l.apply_policy_git, l.apply_policy_rpm, l.apply_policy_v2, l.client_cert_allowlist, l.tls_server_cert_source, l.tls_cert_file, l.tls_key_file, l.tls_pki_server_cert_id, l.tls_client_auth, l.tls_client_ca_file, l.tls_pki_client_ca_id, l.tls_min_version, l.created_at, l.updated_at FROM tls_listeners l WHERE l.public_id = ?`, id)
|
||||||
err = row.Scan(&item.ID, &item.Name, &item.Enabled, &httpAddrs, &httpsAddrs, &item.AuthPolicy, &item.ApplyPolicyAPI, &item.ApplyPolicyGit, &item.ApplyPolicyRPM, &item.ApplyPolicyV2, &certAllowlist, &item.TLSServerCertSource, &item.TLSCertFile, &item.TLSKeyFile, &item.TLSPKIServerCertID, &item.TLSClientAuth, &item.TLSClientCAFile, &item.TLSPKIClientCAID, &item.TLSMinVersion, &item.CreatedAt, &item.UpdatedAt)
|
err = row.Scan(&item.ID, &item.Name, &item.Enabled, &httpAddrs, &httpsAddrs, &item.AuthPolicy, &item.ApplyPolicyAPI, &item.ApplyPolicyGit, &item.ApplyPolicyRPM, &item.ApplyPolicyV2, &certAllowlist, &item.TLSServerCertSource, &item.TLSCertFile, &item.TLSKeyFile, &item.TLSPKIServerCertID, &item.TLSClientAuth, &item.TLSClientCAFile, &item.TLSPKIClientCAID, &item.TLSMinVersion, &item.CreatedAt, &item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -69,7 +69,7 @@ func (s *Store) CreateTLSListener(item models.TLSListener) (models.TLSListener,
|
|||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.CreatedAt = now
|
item.CreatedAt = now
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
_, err = s.DB.Exec(`INSERT INTO tls_listeners (id, name, enabled, http_addrs, https_addrs, auth_policy, apply_policy_api, apply_policy_git, apply_policy_rpm, apply_policy_v2, client_cert_allowlist, tls_server_cert_source, tls_cert_file, tls_key_file, tls_pki_server_cert_id, tls_client_auth, tls_client_ca_file, tls_pki_client_ca_id, tls_min_version, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
_, err = s.DB.Exec(`INSERT INTO tls_listeners (public_id, name, enabled, http_addrs, https_addrs, auth_policy, apply_policy_api, apply_policy_git, apply_policy_rpm, apply_policy_v2, client_cert_allowlist, tls_server_cert_source, tls_cert_file, tls_key_file, tls_pki_server_cert_id, tls_client_auth, tls_client_ca_file, tls_pki_client_ca_id, tls_min_version, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||||
item.ID, item.Name, item.Enabled, strings.Join(item.HTTPAddrs, ","), strings.Join(item.HTTPSAddrs, ","), item.AuthPolicy, item.ApplyPolicyAPI, item.ApplyPolicyGit, item.ApplyPolicyRPM, item.ApplyPolicyV2, strings.Join(item.ClientCertAllowlist, ","), item.TLSServerCertSource, item.TLSCertFile, item.TLSKeyFile, item.TLSPKIServerCertID, item.TLSClientAuth, item.TLSClientCAFile, item.TLSPKIClientCAID, item.TLSMinVersion, item.CreatedAt, item.UpdatedAt)
|
item.ID, item.Name, item.Enabled, strings.Join(item.HTTPAddrs, ","), strings.Join(item.HTTPSAddrs, ","), item.AuthPolicy, item.ApplyPolicyAPI, item.ApplyPolicyGit, item.ApplyPolicyRPM, item.ApplyPolicyV2, strings.Join(item.ClientCertAllowlist, ","), item.TLSServerCertSource, item.TLSCertFile, item.TLSKeyFile, item.TLSPKIServerCertID, item.TLSClientAuth, item.TLSClientCAFile, item.TLSPKIClientCAID, item.TLSMinVersion, item.CreatedAt, item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -82,13 +82,13 @@ func (s *Store) UpdateTLSListener(item models.TLSListener) error {
|
|||||||
var now int64
|
var now int64
|
||||||
now = time.Now().UTC().Unix()
|
now = time.Now().UTC().Unix()
|
||||||
item.UpdatedAt = now
|
item.UpdatedAt = now
|
||||||
_, err = s.DB.Exec(`UPDATE tls_listeners SET name = ?, enabled = ?, http_addrs = ?, https_addrs = ?, auth_policy = ?, apply_policy_api = ?, apply_policy_git = ?, apply_policy_rpm = ?, apply_policy_v2 = ?, client_cert_allowlist = ?, tls_server_cert_source = ?, tls_cert_file = ?, tls_key_file = ?, tls_pki_server_cert_id = ?, tls_client_auth = ?, tls_client_ca_file = ?, tls_pki_client_ca_id = ?, tls_min_version = ?, updated_at = ? WHERE id = ?`,
|
_, err = s.DB.Exec(`UPDATE tls_listeners SET name = ?, enabled = ?, http_addrs = ?, https_addrs = ?, auth_policy = ?, apply_policy_api = ?, apply_policy_git = ?, apply_policy_rpm = ?, apply_policy_v2 = ?, client_cert_allowlist = ?, tls_server_cert_source = ?, tls_cert_file = ?, tls_key_file = ?, tls_pki_server_cert_id = ?, tls_client_auth = ?, tls_client_ca_file = ?, tls_pki_client_ca_id = ?, tls_min_version = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
item.Name, item.Enabled, strings.Join(item.HTTPAddrs, ","), strings.Join(item.HTTPSAddrs, ","), item.AuthPolicy, item.ApplyPolicyAPI, item.ApplyPolicyGit, item.ApplyPolicyRPM, item.ApplyPolicyV2, strings.Join(item.ClientCertAllowlist, ","), item.TLSServerCertSource, item.TLSCertFile, item.TLSKeyFile, item.TLSPKIServerCertID, item.TLSClientAuth, item.TLSClientCAFile, item.TLSPKIClientCAID, item.TLSMinVersion, item.UpdatedAt, item.ID)
|
item.Name, item.Enabled, strings.Join(item.HTTPAddrs, ","), strings.Join(item.HTTPSAddrs, ","), item.AuthPolicy, item.ApplyPolicyAPI, item.ApplyPolicyGit, item.ApplyPolicyRPM, item.ApplyPolicyV2, strings.Join(item.ClientCertAllowlist, ","), item.TLSServerCertSource, item.TLSCertFile, item.TLSKeyFile, item.TLSPKIServerCertID, item.TLSClientAuth, item.TLSClientCAFile, item.TLSPKIClientCAID, item.TLSMinVersion, item.UpdatedAt, item.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) DeleteTLSListener(id string) error {
|
func (s *Store) DeleteTLSListener(id string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.DB.Exec(`DELETE FROM tls_listeners WHERE id = ?`, id)
|
_, err = s.DB.Exec(`DELETE FROM tls_listeners WHERE public_id = ?`, id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,8 @@ func (s *HTTPServer) resolveRepo(repoName string) (models.Repo, models.Project,
|
|||||||
var parts []string
|
var parts []string
|
||||||
var project models.Project
|
var project models.Project
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var err error
|
var err error
|
||||||
var slug string
|
var slug string
|
||||||
var name string
|
var name string
|
||||||
@@ -186,12 +188,18 @@ func (s *HTTPServer) resolveRepo(repoName string) (models.Repo, models.Project,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, project, "", err
|
return repo, project, "", err
|
||||||
}
|
}
|
||||||
if repo.Path == "" {
|
projectStorageID, repoStorageID, err = s.store.GetRepoStorageIDs(repo.ID)
|
||||||
repo.Path = filepath.Join(s.baseDir, project.ID, repo.Name)
|
if err != nil {
|
||||||
|
return repo, project, "", err
|
||||||
}
|
}
|
||||||
|
repo.Path = filepath.Join(s.baseDir, storageIDSegment(projectStorageID), storageIDSegment(repoStorageID))
|
||||||
return repo, project, image, nil
|
return repo, project, image, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func storageIDSegment(id int64) string {
|
||||||
|
return fmt.Sprintf("%016x", id)
|
||||||
|
}
|
||||||
|
|
||||||
func IsReservedImagePath(image string) bool {
|
func IsReservedImagePath(image string) bool {
|
||||||
var cleaned string
|
var cleaned string
|
||||||
var parts []string
|
var parts []string
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import "crypto/rand"
|
|||||||
import "database/sql"
|
import "database/sql"
|
||||||
import "encoding/hex"
|
import "encoding/hex"
|
||||||
import "errors"
|
import "errors"
|
||||||
|
import "fmt"
|
||||||
import "io"
|
import "io"
|
||||||
import "mime/multipart"
|
import "mime/multipart"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
@@ -1630,7 +1631,7 @@ func (api *API) GetRepo(w http.ResponseWriter, r *http.Request, params map[strin
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var err error
|
var err error
|
||||||
var project models.Project
|
var project models.Project
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -1668,6 +1669,8 @@ func (api *API) CreateRepo(w http.ResponseWriter, r *http.Request, params map[st
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var created models.Repo
|
var created models.Repo
|
||||||
var repoType string
|
var repoType string
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
var ok bool
|
var ok bool
|
||||||
var exists bool
|
var exists bool
|
||||||
if !api.requireProjectRole(w, r, params["projectId"], "writer") {
|
if !api.requireProjectRole(w, r, params["projectId"], "writer") {
|
||||||
@@ -1711,42 +1714,48 @@ func (api *API) CreateRepo(w http.ResponseWriter, r *http.Request, params map[st
|
|||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "project not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "project not found"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if repoType == "git" {
|
|
||||||
repoPath = api.Repos.RepoPathFor(project.ID, req.Name)
|
|
||||||
err = api.Repos.InitRepo(repoPath, true)
|
|
||||||
if err != nil {
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if repoType == "rpm" {
|
|
||||||
repoPath = filepath.Join(api.RpmBase, project.ID, req.Name)
|
|
||||||
err = os.MkdirAll(repoPath, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if repoType == "docker" {
|
|
||||||
repoPath = filepath.Join(api.DockerBase, project.ID, req.Name)
|
|
||||||
err = os.MkdirAll(repoPath, 0o755)
|
|
||||||
if err != nil {
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repo = models.Repo{
|
repo = models.Repo{
|
||||||
ID: repoID,
|
ID: repoID,
|
||||||
ProjectID: params["projectId"],
|
ProjectID: params["projectId"],
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Type: repoType,
|
Type: repoType,
|
||||||
Path: repoPath,
|
Path: "",
|
||||||
CreatedBy: user.ID,
|
CreatedBy: user.ID,
|
||||||
}
|
}
|
||||||
created, err = api.Store.CreateRepo(repo)
|
created, err = api.Store.CreateRepo(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.RemoveAll(repoPath)
|
|
||||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
projectStorageID, repoStorageID, err = api.Store.GetRepoStorageIDs(created.ID)
|
||||||
|
if err != nil {
|
||||||
|
_ = api.Store.DeleteRepo(created.ID)
|
||||||
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
repoPath = api.repoStoragePathByType(created.Type, projectStorageID, repoStorageID)
|
||||||
|
if created.Type == "git" {
|
||||||
|
err = os.MkdirAll(filepath.Dir(repoPath), 0o755)
|
||||||
|
if err == nil {
|
||||||
|
err = api.Repos.InitRepo(repoPath, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = os.MkdirAll(repoPath, 0o755)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
_ = api.Store.DeleteRepo(created.ID)
|
||||||
|
_ = os.RemoveAll(repoPath)
|
||||||
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
created.Path = repoPath
|
||||||
|
err = api.Store.UpdateRepo(created)
|
||||||
|
if err != nil {
|
||||||
|
_ = api.Store.DeleteRepo(created.ID)
|
||||||
|
_ = os.RemoveAll(repoPath)
|
||||||
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
var cloneURL string
|
var cloneURL string
|
||||||
var rpmURL string
|
var rpmURL string
|
||||||
var dockerURL string
|
var dockerURL string
|
||||||
@@ -1839,7 +1848,7 @@ func (api *API) AttachForeignRepo(w http.ResponseWriter, r *http.Request, params
|
|||||||
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "repo_id required"})
|
WriteJSON(w, http.StatusBadRequest, map[string]string{"error": "repo_id required"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(req.RepoID)
|
repo, err = api.getRepoResolved(req.RepoID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -1887,7 +1896,7 @@ func (api *API) DetachForeignRepo(w http.ResponseWriter, r *http.Request, params
|
|||||||
if !api.requireProjectRole(w, r, params["projectId"], "admin") {
|
if !api.requireProjectRole(w, r, params["projectId"], "admin") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(params["repoId"])
|
repo, err = api.getRepoResolved(params["repoId"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -1910,10 +1919,9 @@ func (api *API) UpdateRepo(w http.ResponseWriter, r *http.Request, params map[st
|
|||||||
var req updateRepoRequest
|
var req updateRepoRequest
|
||||||
var err error
|
var err error
|
||||||
var newPath string
|
var newPath string
|
||||||
var dir string
|
var projectStorageID int64
|
||||||
var info os.FileInfo
|
var repoStorageID int64
|
||||||
var oldPath string
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -1939,43 +1947,16 @@ func (api *API) UpdateRepo(w http.ResponseWriter, r *http.Request, params map[st
|
|||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "project not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "project not found"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if repo.Type == "git" {
|
projectStorageID, repoStorageID, err = api.Store.GetRepoStorageIDs(repo.ID)
|
||||||
newPath = api.Repos.RepoPathFor(project.ID, req.Name)
|
|
||||||
} else if repo.Type == "rpm" {
|
|
||||||
newPath = filepath.Join(api.RpmBase, project.ID, req.Name)
|
|
||||||
} else if repo.Type == "docker" {
|
|
||||||
newPath = filepath.Join(api.DockerBase, project.ID, req.Name)
|
|
||||||
}
|
|
||||||
if repo.Path != newPath {
|
|
||||||
oldPath = repo.Path
|
|
||||||
info, err = os.Stat(newPath)
|
|
||||||
if err == nil && info != nil {
|
|
||||||
WriteJSON(w, http.StatusConflict, map[string]string{"error": "repository path already exists"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dir = filepath.Dir(newPath)
|
|
||||||
err = os.MkdirAll(dir, 0o755)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = os.Rename(repo.Path, newPath)
|
newPath = api.repoStoragePathByType(repo.Type, projectStorageID, repoStorageID)
|
||||||
if err != nil {
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repo.Name = req.Name
|
repo.Name = req.Name
|
||||||
repo.Path = newPath
|
repo.Path = newPath
|
||||||
err = api.Store.UpdateRepo(repo)
|
err = api.Store.UpdateRepo(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if oldPath != "" {
|
|
||||||
_ = os.Rename(newPath, oldPath)
|
|
||||||
}
|
|
||||||
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
WriteJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2000,7 +1981,7 @@ func (api *API) DeleteRepo(w http.ResponseWriter, r *http.Request, params map[st
|
|||||||
var running bool
|
var running bool
|
||||||
var err error
|
var err error
|
||||||
var temp string
|
var temp string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2105,7 +2086,7 @@ func (api *API) RepoCommits(w http.ResponseWriter, r *http.Request, params map[s
|
|||||||
var query string
|
var query string
|
||||||
var ref string
|
var ref string
|
||||||
var commits []git.Commit
|
var commits []git.Commit
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2143,7 +2124,7 @@ func (api *API) RepoBranches(w http.ResponseWriter, r *http.Request, params map[
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var err error
|
var err error
|
||||||
var branches []string
|
var branches []string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2167,7 +2148,7 @@ func (api *API) RepoBranchesInfo(w http.ResponseWriter, r *http.Request, params
|
|||||||
var ref string
|
var ref string
|
||||||
var query string
|
var query string
|
||||||
var i int
|
var i int
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2202,7 +2183,7 @@ func (api *API) RepoSetDefaultBranch(w http.ResponseWriter, r *http.Request, par
|
|||||||
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2228,7 +2209,7 @@ func (api *API) RepoDeleteBranch(w http.ResponseWriter, r *http.Request, params
|
|||||||
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2260,7 +2241,7 @@ func (api *API) RepoRenameBranch(w http.ResponseWriter, r *http.Request, params
|
|||||||
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2295,7 +2276,7 @@ func (api *API) RepoCreateBranch(w http.ResponseWriter, r *http.Request, params
|
|||||||
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
if !api.requireRepoRole(w, r, params["id"], "admin") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2323,7 +2304,7 @@ func (api *API) RepoTree(w http.ResponseWriter, r *http.Request, params map[stri
|
|||||||
var ref string
|
var ref string
|
||||||
var path string
|
var path string
|
||||||
var entries []git.TreeEntry
|
var entries []git.TreeEntry
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2351,7 +2332,7 @@ func (api *API) RepoBlob(w http.ResponseWriter, r *http.Request, params map[stri
|
|||||||
var ref string
|
var ref string
|
||||||
var path string
|
var path string
|
||||||
var content string
|
var content string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2380,7 +2361,7 @@ func (api *API) RepoBlobRaw(w http.ResponseWriter, r *http.Request, params map[s
|
|||||||
var path string
|
var path string
|
||||||
var content []byte
|
var content []byte
|
||||||
var contentType string
|
var contentType string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2414,7 +2395,7 @@ func (api *API) RepoFileHistory(w http.ResponseWriter, r *http.Request, params m
|
|||||||
var v string
|
var v string
|
||||||
var i int
|
var i int
|
||||||
var commits []git.Commit
|
var commits []git.Commit
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2450,7 +2431,7 @@ func (api *API) RepoFileDiff(w http.ResponseWriter, r *http.Request, params map[
|
|||||||
var ref string
|
var ref string
|
||||||
var path string
|
var path string
|
||||||
var diff string
|
var diff string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2477,7 +2458,7 @@ func (api *API) RepoCommitDetail(w http.ResponseWriter, r *http.Request, params
|
|||||||
var err error
|
var err error
|
||||||
var hash string
|
var hash string
|
||||||
var detail git.CommitDetail
|
var detail git.CommitDetail
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2503,7 +2484,7 @@ func (api *API) RepoCommitDiff(w http.ResponseWriter, r *http.Request, params ma
|
|||||||
var err error
|
var err error
|
||||||
var hash string
|
var hash string
|
||||||
var diff string
|
var diff string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2533,7 +2514,7 @@ func (api *API) RepoCompare(w http.ResponseWriter, r *http.Request, params map[s
|
|||||||
var v string
|
var v string
|
||||||
var i int
|
var i int
|
||||||
var commits []git.Commit
|
var commits []git.Commit
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2571,7 +2552,7 @@ func (api *API) RepoStats(w http.ResponseWriter, r *http.Request, params map[str
|
|||||||
var ref string
|
var ref string
|
||||||
var commits []git.Commit
|
var commits []git.Commit
|
||||||
var stats repoStatsResponse
|
var stats repoStatsResponse
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2640,7 +2621,7 @@ func (api *API) RepoRPMPackages(w http.ResponseWriter, r *http.Request, params m
|
|||||||
var query string
|
var query string
|
||||||
var filtered []rpm.PackageSummary
|
var filtered []rpm.PackageSummary
|
||||||
var i int
|
var i int
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2676,7 +2657,7 @@ func (api *API) RepoRPMPackage(w http.ResponseWriter, r *http.Request, params ma
|
|||||||
var err error
|
var err error
|
||||||
var filename string
|
var filename string
|
||||||
var detail rpm.PackageDetail
|
var detail rpm.PackageDetail
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2732,7 +2713,7 @@ func (api *API) RepoRPMCreateSubdir(w http.ResponseWriter, r *http.Request, para
|
|||||||
var allowDelete bool
|
var allowDelete bool
|
||||||
var tlsInsecureSkipVerify bool
|
var tlsInsecureSkipVerify bool
|
||||||
var syncIntervalSec int64
|
var syncIntervalSec int64
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2863,7 +2844,7 @@ func (api *API) RepoRPMGetSubdir(w http.ResponseWriter, r *http.Request, params
|
|||||||
var normalizedPath string
|
var normalizedPath string
|
||||||
var config models.RPMRepoDir
|
var config models.RPMRepoDir
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2903,7 +2884,7 @@ func (api *API) RepoRPMSyncSubdir(w http.ResponseWriter, r *http.Request, params
|
|||||||
var normalizedPath string
|
var normalizedPath string
|
||||||
var config models.RPMRepoDir
|
var config models.RPMRepoDir
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -2965,7 +2946,7 @@ func (api *API) RepoRPMRebuildSubdirMetadata(w http.ResponseWriter, r *http.Requ
|
|||||||
var fullPath string
|
var fullPath string
|
||||||
var repodataPath string
|
var repodataPath string
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3013,7 +2994,7 @@ func (api *API) RepoRPMCancelSubdirSync(w http.ResponseWriter, r *http.Request,
|
|||||||
var config models.RPMRepoDir
|
var config models.RPMRepoDir
|
||||||
var canceled bool
|
var canceled bool
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3071,7 +3052,7 @@ func (api *API) repoRPMSetSyncEnabled(w http.ResponseWriter, r *http.Request, pa
|
|||||||
var config models.RPMRepoDir
|
var config models.RPMRepoDir
|
||||||
var cancelRequested bool
|
var cancelRequested bool
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3125,7 +3106,7 @@ func (api *API) RepoRPMMirrorRuns(w http.ResponseWriter, r *http.Request, params
|
|||||||
var limit int
|
var limit int
|
||||||
var runs []models.RPMMirrorRun
|
var runs []models.RPMMirrorRun
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3168,7 +3149,7 @@ func (api *API) RepoRPMClearMirrorRuns(w http.ResponseWriter, r *http.Request, p
|
|||||||
var normalizedPath string
|
var normalizedPath string
|
||||||
var count int64
|
var count int64
|
||||||
var err error
|
var err error
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3217,7 +3198,7 @@ func (api *API) RepoRPMDeleteSubdir(w http.ResponseWriter, r *http.Request, para
|
|||||||
var relPathClean string
|
var relPathClean string
|
||||||
var parentPath string
|
var parentPath string
|
||||||
var repodataPath string
|
var repodataPath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3372,7 +3353,7 @@ func (api *API) RepoRPMRenameSubdir(w http.ResponseWriter, r *http.Request, para
|
|||||||
var busy bool
|
var busy bool
|
||||||
var busyPath string
|
var busyPath string
|
||||||
var busyReason string
|
var busyReason string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3644,7 +3625,7 @@ func (api *API) RepoRPMDeleteFile(w http.ResponseWriter, r *http.Request, params
|
|||||||
var parentPath string
|
var parentPath string
|
||||||
var repodataPath string
|
var repodataPath string
|
||||||
var lower string
|
var lower string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3730,7 +3711,7 @@ func (api *API) RepoRPMFile(w http.ResponseWriter, r *http.Request, params map[s
|
|||||||
var allowed bool
|
var allowed bool
|
||||||
var file *os.File
|
var file *os.File
|
||||||
var size int64
|
var size int64
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3796,7 +3777,7 @@ func (api *API) RepoRPMTree(w http.ResponseWriter, r *http.Request, params map[s
|
|||||||
var i int
|
var i int
|
||||||
var entryPath string
|
var entryPath string
|
||||||
var repodataPath string
|
var repodataPath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -3879,7 +3860,7 @@ func (api *API) RepoRPMUpload(w http.ResponseWriter, r *http.Request, params map
|
|||||||
var info os.FileInfo
|
var info os.FileInfo
|
||||||
var oldTemp string
|
var oldTemp string
|
||||||
var ts string
|
var ts string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4022,7 +4003,7 @@ func (api *API) RepoDockerTags(w http.ResponseWriter, r *http.Request, params ma
|
|||||||
var tags []docker.TagInfo
|
var tags []docker.TagInfo
|
||||||
var image string
|
var image string
|
||||||
var imagePath string
|
var imagePath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4051,7 +4032,7 @@ func (api *API) RepoDockerManifest(w http.ResponseWriter, r *http.Request, param
|
|||||||
var detail docker.ManifestDetail
|
var detail docker.ManifestDetail
|
||||||
var image string
|
var image string
|
||||||
var imagePath string
|
var imagePath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4086,7 +4067,7 @@ func (api *API) RepoDockerImages(w http.ResponseWriter, r *http.Request, params
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var err error
|
var err error
|
||||||
var images []string
|
var images []string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4299,7 +4280,7 @@ func (api *API) RepoDockerDeleteTag(w http.ResponseWriter, r *http.Request, para
|
|||||||
var image string
|
var image string
|
||||||
var tag string
|
var tag string
|
||||||
var imagePath string
|
var imagePath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4330,7 +4311,7 @@ func (api *API) RepoDockerDeleteImage(w http.ResponseWriter, r *http.Request, pa
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var err error
|
var err error
|
||||||
var image string
|
var image string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4359,7 +4340,7 @@ func (api *API) RepoDockerRenameTag(w http.ResponseWriter, r *http.Request, para
|
|||||||
var from string
|
var from string
|
||||||
var to string
|
var to string
|
||||||
var imagePath string
|
var imagePath string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -4402,7 +4383,7 @@ func (api *API) RepoDockerRenameImage(w http.ResponseWriter, r *http.Request, pa
|
|||||||
var req repoDockerRenameImageRequest
|
var req repoDockerRenameImageRequest
|
||||||
var from string
|
var from string
|
||||||
var to string
|
var to string
|
||||||
repo, err = api.Store.GetRepo(params["id"])
|
repo, err = api.getRepoResolved(params["id"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
WriteJSON(w, http.StatusNotFound, map[string]string{"error": "repo not found"})
|
||||||
return
|
return
|
||||||
@@ -5518,3 +5499,46 @@ func (api *API) dockerURL(projectSlug, repoName string) string {
|
|||||||
base = strings.TrimRight(api.Cfg.PublicBaseURL, "/")
|
base = strings.TrimRight(api.Cfg.PublicBaseURL, "/")
|
||||||
return base + "/v2/" + projectSlug + "/" + repoName
|
return base + "/v2/" + projectSlug + "/" + repoName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) getRepoResolved(repoID string) (models.Repo, error) {
|
||||||
|
var repo models.Repo
|
||||||
|
var err error
|
||||||
|
repo, err = api.Store.GetRepo(repoID)
|
||||||
|
if err != nil {
|
||||||
|
return repo, err
|
||||||
|
}
|
||||||
|
err = api.ensureRepoPath(&repo)
|
||||||
|
if err != nil {
|
||||||
|
return repo, err
|
||||||
|
}
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) ensureRepoPath(repo *models.Repo) error {
|
||||||
|
var err error
|
||||||
|
var projectStorageID int64
|
||||||
|
var repoStorageID int64
|
||||||
|
projectStorageID, repoStorageID, err = api.Store.GetRepoStorageIDs(repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
repo.Path = api.repoStoragePathByType(repo.Type, projectStorageID, repoStorageID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) repoStoragePathByType(repoType string, projectID int64, repoID int64) string {
|
||||||
|
var projectPart string
|
||||||
|
var repoPart string
|
||||||
|
projectPart = fmt.Sprintf("%016x", projectID)
|
||||||
|
repoPart = fmt.Sprintf("%016x", repoID)
|
||||||
|
if repoType == "git" {
|
||||||
|
return filepath.Join(api.Repos.BaseDir, projectPart, repoPart+".git")
|
||||||
|
}
|
||||||
|
if repoType == "rpm" {
|
||||||
|
return filepath.Join(api.RpmBase, projectPart, repoPart)
|
||||||
|
}
|
||||||
|
if repoType == "docker" {
|
||||||
|
return filepath.Join(api.DockerBase, projectPart, repoPart)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
PRAGMA foreign_keys = ON;
|
PRAGMA foreign_keys = ON;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
username TEXT NOT NULL UNIQUE,
|
username TEXT NOT NULL UNIQUE,
|
||||||
display_name TEXT NOT NULL,
|
display_name TEXT NOT NULL,
|
||||||
email TEXT NOT NULL,
|
email TEXT NOT NULL,
|
||||||
@@ -9,12 +10,13 @@ CREATE TABLE IF NOT EXISTS users (
|
|||||||
is_admin INTEGER NOT NULL DEFAULT 0,
|
is_admin INTEGER NOT NULL DEFAULT 0,
|
||||||
auth_source TEXT NOT NULL DEFAULT 'db',
|
auth_source TEXT NOT NULL DEFAULT 'db',
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
updated_at TIMESTAMP NOT NULL
|
updated_at TIMESTAMP NOT NULL,
|
||||||
|
disabled INTEGER NOT NULL DEFAULT 0
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS sessions (
|
CREATE TABLE IF NOT EXISTS sessions (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
user_id TEXT NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
token TEXT NOT NULL UNIQUE,
|
token TEXT NOT NULL UNIQUE,
|
||||||
expires_at TIMESTAMP NOT NULL,
|
expires_at TIMESTAMP NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
@@ -22,19 +24,25 @@ CREATE TABLE IF NOT EXISTS sessions (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS projects (
|
CREATE TABLE IF NOT EXISTS projects (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
slug TEXT NOT NULL UNIQUE,
|
slug TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
home_page TEXT NOT NULL DEFAULT 'info',
|
||||||
|
created_by INTEGER NOT NULL,
|
||||||
|
updated_by INTEGER NOT NULL DEFAULT 0,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
updated_at TIMESTAMP NOT NULL,
|
updated_at TIMESTAMP NOT NULL,
|
||||||
|
created_at_unix INTEGER NOT NULL DEFAULT 0,
|
||||||
|
updated_at_unix INTEGER NOT NULL DEFAULT 0,
|
||||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||||
|
FOREIGN KEY (updated_by) REFERENCES users(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS project_members (
|
CREATE TABLE IF NOT EXISTS project_members (
|
||||||
project_id TEXT NOT NULL,
|
project_id INTEGER NOT NULL,
|
||||||
user_id TEXT NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
role TEXT NOT NULL,
|
role TEXT NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
PRIMARY KEY (project_id, user_id),
|
PRIMARY KEY (project_id, user_id),
|
||||||
@@ -43,24 +51,27 @@ CREATE TABLE IF NOT EXISTS project_members (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS repos (
|
CREATE TABLE IF NOT EXISTS repos (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
project_id TEXT NOT NULL,
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL DEFAULT 'git',
|
||||||
path TEXT NOT NULL,
|
path TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS issues (
|
CREATE TABLE IF NOT EXISTS issues (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
project_id TEXT NOT NULL,
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
body TEXT NOT NULL,
|
body TEXT NOT NULL,
|
||||||
status TEXT NOT NULL,
|
status TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
assignee_id TEXT,
|
assignee_id INTEGER,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
updated_at TIMESTAMP NOT NULL,
|
updated_at TIMESTAMP NOT NULL,
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
@@ -69,22 +80,24 @@ CREATE TABLE IF NOT EXISTS issues (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS issue_comments (
|
CREATE TABLE IF NOT EXISTS issue_comments (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
issue_id TEXT NOT NULL,
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
issue_id INTEGER NOT NULL,
|
||||||
body TEXT NOT NULL,
|
body TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
|
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS wiki_pages (
|
CREATE TABLE IF NOT EXISTS wiki_pages (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
project_id TEXT NOT NULL,
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
title TEXT NOT NULL,
|
title TEXT NOT NULL,
|
||||||
slug TEXT NOT NULL,
|
slug TEXT NOT NULL,
|
||||||
body TEXT NOT NULL,
|
body TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
updated_at TIMESTAMP NOT NULL,
|
updated_at TIMESTAMP NOT NULL,
|
||||||
UNIQUE (project_id, slug),
|
UNIQUE (project_id, slug),
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
@@ -92,20 +105,203 @@ CREATE TABLE IF NOT EXISTS wiki_pages (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS uploads (
|
CREATE TABLE IF NOT EXISTS uploads (
|
||||||
id TEXT PRIMARY KEY,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
project_id TEXT NOT NULL,
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
filename TEXT NOT NULL,
|
filename TEXT NOT NULL,
|
||||||
content_type TEXT NOT NULL,
|
content_type TEXT NOT NULL,
|
||||||
size INTEGER NOT NULL,
|
size INTEGER NOT NULL,
|
||||||
storage_path TEXT NOT NULL,
|
storage_path TEXT NOT NULL,
|
||||||
created_by TEXT NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (created_by) REFERENCES users(id)
|
FOREIGN KEY (created_by) REFERENCES users(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS project_repos (
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
|
repo_id INTEGER NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
PRIMARY KEY (project_id, repo_id),
|
||||||
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS app_settings (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS api_keys (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
token_hash TEXT NOT NULL,
|
||||||
|
token_prefix TEXT NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
last_used_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
expires_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
disabled INTEGER NOT NULL DEFAULT 0,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS pki_cas (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
parent_ca_id INTEGER,
|
||||||
|
is_root INTEGER NOT NULL DEFAULT 0,
|
||||||
|
cert_pem TEXT NOT NULL,
|
||||||
|
key_pem TEXT NOT NULL,
|
||||||
|
serial_counter INTEGER NOT NULL DEFAULT 1,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active',
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(parent_ca_id) REFERENCES pki_cas(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS pki_certs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
ca_id INTEGER,
|
||||||
|
serial_hex TEXT NOT NULL,
|
||||||
|
common_name TEXT NOT NULL,
|
||||||
|
san_dns TEXT NOT NULL DEFAULT '',
|
||||||
|
san_ips TEXT NOT NULL DEFAULT '',
|
||||||
|
is_ca INTEGER NOT NULL DEFAULT 0,
|
||||||
|
cert_pem TEXT NOT NULL,
|
||||||
|
key_pem TEXT NOT NULL,
|
||||||
|
not_before INTEGER NOT NULL,
|
||||||
|
not_after INTEGER NOT NULL,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active',
|
||||||
|
revoked_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
revocation_reason TEXT NOT NULL DEFAULT '',
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(ca_id) REFERENCES pki_cas(id) ON DELETE CASCADE,
|
||||||
|
UNIQUE(ca_id, serial_hex)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tls_listeners (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
enabled INTEGER NOT NULL DEFAULT 1,
|
||||||
|
http_addrs TEXT NOT NULL DEFAULT '',
|
||||||
|
https_addrs TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_server_cert_source TEXT NOT NULL DEFAULT 'files',
|
||||||
|
tls_cert_file TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_key_file TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_pki_server_cert_id TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_client_auth TEXT NOT NULL DEFAULT 'none',
|
||||||
|
tls_client_ca_file TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_pki_client_ca_id TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_min_version TEXT NOT NULL DEFAULT '1.2',
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
auth_policy TEXT NOT NULL DEFAULT 'default',
|
||||||
|
apply_policy_api INTEGER NOT NULL DEFAULT 0,
|
||||||
|
apply_policy_git INTEGER NOT NULL DEFAULT 0,
|
||||||
|
apply_policy_rpm INTEGER NOT NULL DEFAULT 0,
|
||||||
|
apply_policy_v2 INTEGER NOT NULL DEFAULT 0,
|
||||||
|
client_cert_allowlist TEXT NOT NULL DEFAULT ''
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS service_principals (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
description TEXT NOT NULL DEFAULT '',
|
||||||
|
disabled INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
is_admin INTEGER NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS cert_principal_bindings (
|
||||||
|
fingerprint TEXT PRIMARY KEY,
|
||||||
|
principal_id INTEGER NOT NULL,
|
||||||
|
enabled INTEGER NOT NULL DEFAULT 1,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (principal_id) REFERENCES service_principals(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS principal_project_roles (
|
||||||
|
principal_id INTEGER NOT NULL,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
|
role TEXT NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY (principal_id, project_id),
|
||||||
|
FOREIGN KEY (principal_id) REFERENCES service_principals(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS rpm_repo_dirs (
|
||||||
|
repo_id INTEGER NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
mode TEXT NOT NULL DEFAULT 'local',
|
||||||
|
allow_delete INTEGER NOT NULL DEFAULT 0,
|
||||||
|
remote_url TEXT NOT NULL DEFAULT '',
|
||||||
|
connect_host TEXT NOT NULL DEFAULT '',
|
||||||
|
host_header TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_server_name TEXT NOT NULL DEFAULT '',
|
||||||
|
tls_insecure_skip_verify INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_interval_sec INTEGER NOT NULL DEFAULT 300,
|
||||||
|
sync_enabled INTEGER NOT NULL DEFAULT 1,
|
||||||
|
dirty INTEGER NOT NULL DEFAULT 1,
|
||||||
|
next_sync_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_running INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_status TEXT NOT NULL DEFAULT 'idle',
|
||||||
|
sync_error TEXT NOT NULL DEFAULT '',
|
||||||
|
sync_step TEXT NOT NULL DEFAULT '',
|
||||||
|
sync_total INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_done INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_failed INTEGER NOT NULL DEFAULT 0,
|
||||||
|
sync_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
|
last_sync_started_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
last_sync_finished_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
last_sync_success_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
last_synced_revision TEXT NOT NULL DEFAULT '',
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
PRIMARY KEY (repo_id, path),
|
||||||
|
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS rpm_mirror_runs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
public_id TEXT NOT NULL UNIQUE,
|
||||||
|
repo_id INTEGER NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
started_at INTEGER NOT NULL,
|
||||||
|
finished_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
status TEXT NOT NULL DEFAULT 'running',
|
||||||
|
step TEXT NOT NULL DEFAULT '',
|
||||||
|
total INTEGER NOT NULL DEFAULT 0,
|
||||||
|
done INTEGER NOT NULL DEFAULT 0,
|
||||||
|
failed INTEGER NOT NULL DEFAULT 0,
|
||||||
|
deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
|
revision TEXT NOT NULL DEFAULT '',
|
||||||
|
error TEXT NOT NULL DEFAULT '',
|
||||||
|
FOREIGN KEY(repo_id, path) REFERENCES rpm_repo_dirs(repo_id, path) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_disabled ON users(disabled);
|
||||||
CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name);
|
CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name);
|
||||||
CREATE INDEX IF NOT EXISTS idx_repos_project ON repos(project_id);
|
CREATE INDEX IF NOT EXISTS idx_repos_project ON repos(project_id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_repos_project_name_type ON repos(project_id, name, type);
|
||||||
CREATE INDEX IF NOT EXISTS idx_issues_project ON issues(project_id);
|
CREATE INDEX IF NOT EXISTS idx_issues_project ON issues(project_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_wiki_project ON wiki_pages(project_id);
|
CREATE INDEX IF NOT EXISTS idx_wiki_project ON wiki_pages(project_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_uploads_project ON uploads(project_id);
|
CREATE INDEX IF NOT EXISTS idx_uploads_project ON uploads(project_id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_api_keys_hash ON api_keys(token_hash);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_api_keys_expires_at ON api_keys(expires_at);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_api_keys_disabled ON api_keys(disabled);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_project_repos_project ON project_repos(project_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_project_repos_repo ON project_repos(repo_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_pki_cas_parent ON pki_cas(parent_ca_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_pki_certs_ca ON pki_certs(ca_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_cert_principal_bindings_principal_id ON cert_principal_bindings(principal_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_principal_project_roles_project_id ON principal_project_roles(project_id);
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
PRAGMA foreign_keys = ON;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS project_repos (
|
|
||||||
project_id TEXT NOT NULL,
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
created_at TIMESTAMP NOT NULL,
|
|
||||||
PRIMARY KEY (project_id, repo_id),
|
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_project_repos_project ON project_repos(project_id);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_project_repos_repo ON project_repos(repo_id);
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
ALTER TABLE projects ADD COLUMN updated_by TEXT NOT NULL DEFAULT '';
|
|
||||||
ALTER TABLE projects ADD COLUMN created_at_unix INTEGER NOT NULL DEFAULT 0;
|
|
||||||
ALTER TABLE projects ADD COLUMN updated_at_unix INTEGER NOT NULL DEFAULT 0;
|
|
||||||
|
|
||||||
UPDATE projects
|
|
||||||
SET
|
|
||||||
updated_by = created_by,
|
|
||||||
created_at_unix = COALESCE(CAST(strftime('%s', created_at) AS INTEGER), 0),
|
|
||||||
updated_at_unix = COALESCE(CAST(strftime('%s', updated_at) AS INTEGER), 0)
|
|
||||||
WHERE created_at_unix = 0 OR updated_at_unix = 0 OR updated_by = '';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
PRAGMA foreign_keys = ON;
|
|
||||||
|
|
||||||
ALTER TABLE repos ADD COLUMN type TEXT NOT NULL DEFAULT 'git';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
PRAGMA foreign_keys = ON;
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_repos_project_name_type ON repos(project_id, name, type);
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS api_keys (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
user_id TEXT NOT NULL,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
token_hash TEXT NOT NULL,
|
|
||||||
token_prefix TEXT NOT NULL,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
last_used_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_api_keys_hash ON api_keys(token_hash);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE projects ADD COLUMN home_page TEXT NOT NULL DEFAULT 'info';
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
ALTER TABLE api_keys ADD COLUMN expires_at INTEGER NOT NULL DEFAULT 0;
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_api_keys_expires_at ON api_keys(expires_at);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
ALTER TABLE users ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0;
|
|
||||||
ALTER TABLE api_keys ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0;
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_users_disabled ON users(disabled);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_api_keys_disabled ON api_keys(disabled);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS app_settings (
|
|
||||||
key TEXT PRIMARY KEY,
|
|
||||||
value TEXT NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS pki_cas (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE,
|
|
||||||
parent_ca_id TEXT,
|
|
||||||
is_root INTEGER NOT NULL DEFAULT 0,
|
|
||||||
cert_pem TEXT NOT NULL,
|
|
||||||
key_pem TEXT NOT NULL,
|
|
||||||
serial_counter INTEGER NOT NULL DEFAULT 1,
|
|
||||||
status TEXT NOT NULL DEFAULT 'active',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY(parent_ca_id) REFERENCES pki_cas(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS pki_certs (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
ca_id TEXT NOT NULL,
|
|
||||||
serial_hex TEXT NOT NULL,
|
|
||||||
common_name TEXT NOT NULL,
|
|
||||||
san_dns TEXT NOT NULL DEFAULT '',
|
|
||||||
san_ips TEXT NOT NULL DEFAULT '',
|
|
||||||
is_ca INTEGER NOT NULL DEFAULT 0,
|
|
||||||
cert_pem TEXT NOT NULL,
|
|
||||||
key_pem TEXT NOT NULL,
|
|
||||||
not_before INTEGER NOT NULL,
|
|
||||||
not_after INTEGER NOT NULL,
|
|
||||||
status TEXT NOT NULL DEFAULT 'active',
|
|
||||||
revoked_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
revocation_reason TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY(ca_id) REFERENCES pki_cas(id) ON DELETE CASCADE,
|
|
||||||
UNIQUE(ca_id, serial_hex)
|
|
||||||
);
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS tls_listeners (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE,
|
|
||||||
enabled INTEGER NOT NULL DEFAULT 1,
|
|
||||||
http_addrs TEXT NOT NULL DEFAULT '',
|
|
||||||
https_addrs TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_server_cert_source TEXT NOT NULL DEFAULT 'files',
|
|
||||||
tls_cert_file TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_key_file TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_pki_server_cert_id TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_client_auth TEXT NOT NULL DEFAULT 'none',
|
|
||||||
tls_client_ca_file TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_pki_client_ca_id TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_min_version TEXT NOT NULL DEFAULT '1.2',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
ALTER TABLE tls_listeners ADD COLUMN auth_policy TEXT NOT NULL DEFAULT 'default';
|
|
||||||
ALTER TABLE tls_listeners ADD COLUMN apply_policy_api INTEGER NOT NULL DEFAULT 1;
|
|
||||||
ALTER TABLE tls_listeners ADD COLUMN apply_policy_git INTEGER NOT NULL DEFAULT 1;
|
|
||||||
ALTER TABLE tls_listeners ADD COLUMN apply_policy_rpm INTEGER NOT NULL DEFAULT 1;
|
|
||||||
ALTER TABLE tls_listeners ADD COLUMN apply_policy_v2 INTEGER NOT NULL DEFAULT 1;
|
|
||||||
ALTER TABLE tls_listeners ADD COLUMN client_cert_allowlist TEXT NOT NULL DEFAULT '';
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS service_principals (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
name TEXT NOT NULL UNIQUE,
|
|
||||||
description TEXT NOT NULL DEFAULT '',
|
|
||||||
disabled INTEGER NOT NULL DEFAULT 0,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS cert_principal_bindings (
|
|
||||||
fingerprint TEXT PRIMARY KEY,
|
|
||||||
principal_id TEXT NOT NULL,
|
|
||||||
enabled INTEGER NOT NULL DEFAULT 1,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY (principal_id) REFERENCES service_principals(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
ALTER TABLE service_principals ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS principal_project_roles (
|
|
||||||
principal_id TEXT NOT NULL,
|
|
||||||
project_id TEXT NOT NULL,
|
|
||||||
role TEXT NOT NULL,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (principal_id, project_id),
|
|
||||||
FOREIGN KEY (principal_id) REFERENCES service_principals(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS pki_certs_new (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
ca_id TEXT,
|
|
||||||
serial_hex TEXT NOT NULL,
|
|
||||||
common_name TEXT NOT NULL,
|
|
||||||
san_dns TEXT NOT NULL DEFAULT '',
|
|
||||||
san_ips TEXT NOT NULL DEFAULT '',
|
|
||||||
is_ca INTEGER NOT NULL DEFAULT 0,
|
|
||||||
cert_pem TEXT NOT NULL,
|
|
||||||
key_pem TEXT NOT NULL,
|
|
||||||
not_before INTEGER NOT NULL,
|
|
||||||
not_after INTEGER NOT NULL,
|
|
||||||
status TEXT NOT NULL DEFAULT 'active',
|
|
||||||
revoked_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
revocation_reason TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
FOREIGN KEY(ca_id) REFERENCES pki_cas(id) ON DELETE CASCADE,
|
|
||||||
UNIQUE(ca_id, serial_hex)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO pki_certs_new (
|
|
||||||
id, ca_id, serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem,
|
|
||||||
not_before, not_after, status, revoked_at, revocation_reason, created_at
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
id, ca_id, serial_hex, common_name, san_dns, san_ips, is_ca, cert_pem, key_pem,
|
|
||||||
not_before, not_after, status, revoked_at, revocation_reason, created_at
|
|
||||||
FROM pki_certs;
|
|
||||||
|
|
||||||
DROP TABLE pki_certs;
|
|
||||||
ALTER TABLE pki_certs_new RENAME TO pki_certs;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS rpm_repo_dirs (
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
path TEXT NOT NULL,
|
|
||||||
mode TEXT NOT NULL DEFAULT 'local',
|
|
||||||
remote_url TEXT NOT NULL DEFAULT '',
|
|
||||||
connect_host TEXT NOT NULL DEFAULT '',
|
|
||||||
host_header TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_server_name TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_insecure_skip_verify INTEGER NOT NULL DEFAULT 0,
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (repo_id, path),
|
|
||||||
FOREIGN KEY(repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
PRAGMA foreign_keys = OFF;
|
|
||||||
|
|
||||||
BEGIN TRANSACTION;
|
|
||||||
|
|
||||||
ALTER TABLE rpm_repo_dirs RENAME TO rpm_repo_dirs_old;
|
|
||||||
|
|
||||||
CREATE TABLE rpm_repo_dirs (
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
path TEXT NOT NULL,
|
|
||||||
mode TEXT NOT NULL DEFAULT 'local',
|
|
||||||
remote_url TEXT NOT NULL DEFAULT '',
|
|
||||||
connect_host TEXT NOT NULL DEFAULT '',
|
|
||||||
host_header TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_server_name TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_insecure_skip_verify INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_interval_sec INTEGER NOT NULL DEFAULT 300,
|
|
||||||
dirty INTEGER NOT NULL DEFAULT 1,
|
|
||||||
next_sync_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_running INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_status TEXT NOT NULL DEFAULT 'idle',
|
|
||||||
sync_error TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_step TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_total INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_done INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_failed INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_started_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_finished_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_success_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_synced_revision TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (repo_id, path),
|
|
||||||
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO rpm_repo_dirs (
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
sync_interval_sec,
|
|
||||||
dirty,
|
|
||||||
next_sync_at,
|
|
||||||
sync_running,
|
|
||||||
sync_status,
|
|
||||||
sync_error,
|
|
||||||
sync_step,
|
|
||||||
sync_total,
|
|
||||||
sync_done,
|
|
||||||
sync_failed,
|
|
||||||
sync_deleted,
|
|
||||||
last_sync_started_at,
|
|
||||||
last_sync_finished_at,
|
|
||||||
last_sync_success_at,
|
|
||||||
last_synced_revision,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
300,
|
|
||||||
CASE WHEN mode = 'mirror' THEN 1 ELSE 0 END,
|
|
||||||
CASE WHEN mode = 'mirror' THEN 0 ELSE 0 END,
|
|
||||||
0,
|
|
||||||
'idle',
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
'',
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
FROM rpm_repo_dirs_old;
|
|
||||||
|
|
||||||
DROP TABLE rpm_repo_dirs_old;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
PRAGMA foreign_keys = ON;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS rpm_mirror_runs (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
path TEXT NOT NULL,
|
|
||||||
started_at INTEGER NOT NULL,
|
|
||||||
finished_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
status TEXT NOT NULL DEFAULT 'running',
|
|
||||||
step TEXT NOT NULL DEFAULT '',
|
|
||||||
total INTEGER NOT NULL DEFAULT 0,
|
|
||||||
done INTEGER NOT NULL DEFAULT 0,
|
|
||||||
failed INTEGER NOT NULL DEFAULT 0,
|
|
||||||
deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
revision TEXT NOT NULL DEFAULT '',
|
|
||||||
error TEXT NOT NULL DEFAULT '',
|
|
||||||
FOREIGN KEY(repo_id, path) REFERENCES rpm_repo_dirs(repo_id, path) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_rpm_mirror_runs_repo_path_started
|
|
||||||
ON rpm_mirror_runs (repo_id, path, started_at DESC);
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
PRAGMA foreign_keys = OFF;
|
|
||||||
|
|
||||||
BEGIN TRANSACTION;
|
|
||||||
|
|
||||||
CREATE TABLE rpm_repo_dirs_new (
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
path TEXT NOT NULL,
|
|
||||||
mode TEXT NOT NULL DEFAULT 'local',
|
|
||||||
remote_url TEXT NOT NULL DEFAULT '',
|
|
||||||
connect_host TEXT NOT NULL DEFAULT '',
|
|
||||||
host_header TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_server_name TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_insecure_skip_verify INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_interval_sec INTEGER NOT NULL DEFAULT 300,
|
|
||||||
sync_enabled INTEGER NOT NULL DEFAULT 1,
|
|
||||||
dirty INTEGER NOT NULL DEFAULT 1,
|
|
||||||
next_sync_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_running INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_status TEXT NOT NULL DEFAULT 'idle',
|
|
||||||
sync_error TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_step TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_total INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_done INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_failed INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_started_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_finished_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_success_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_synced_revision TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (repo_id, path),
|
|
||||||
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO rpm_repo_dirs_new (
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
sync_interval_sec,
|
|
||||||
sync_enabled,
|
|
||||||
dirty,
|
|
||||||
next_sync_at,
|
|
||||||
sync_running,
|
|
||||||
sync_status,
|
|
||||||
sync_error,
|
|
||||||
sync_step,
|
|
||||||
sync_total,
|
|
||||||
sync_done,
|
|
||||||
sync_failed,
|
|
||||||
sync_deleted,
|
|
||||||
last_sync_started_at,
|
|
||||||
last_sync_finished_at,
|
|
||||||
last_sync_success_at,
|
|
||||||
last_synced_revision,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
sync_interval_sec,
|
|
||||||
1,
|
|
||||||
dirty,
|
|
||||||
next_sync_at,
|
|
||||||
sync_running,
|
|
||||||
sync_status,
|
|
||||||
sync_error,
|
|
||||||
sync_step,
|
|
||||||
sync_total,
|
|
||||||
sync_done,
|
|
||||||
sync_failed,
|
|
||||||
sync_deleted,
|
|
||||||
last_sync_started_at,
|
|
||||||
last_sync_finished_at,
|
|
||||||
last_sync_success_at,
|
|
||||||
last_synced_revision,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
FROM rpm_repo_dirs;
|
|
||||||
|
|
||||||
DROP TABLE rpm_repo_dirs;
|
|
||||||
|
|
||||||
ALTER TABLE rpm_repo_dirs_new RENAME TO rpm_repo_dirs;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
PRAGMA foreign_keys = ON;
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
PRAGMA foreign_keys = OFF;
|
|
||||||
|
|
||||||
BEGIN TRANSACTION;
|
|
||||||
|
|
||||||
CREATE TABLE rpm_repo_dirs_new (
|
|
||||||
repo_id TEXT NOT NULL,
|
|
||||||
path TEXT NOT NULL,
|
|
||||||
mode TEXT NOT NULL DEFAULT 'local',
|
|
||||||
allow_delete INTEGER NOT NULL DEFAULT 0,
|
|
||||||
remote_url TEXT NOT NULL DEFAULT '',
|
|
||||||
connect_host TEXT NOT NULL DEFAULT '',
|
|
||||||
host_header TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_server_name TEXT NOT NULL DEFAULT '',
|
|
||||||
tls_insecure_skip_verify INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_interval_sec INTEGER NOT NULL DEFAULT 300,
|
|
||||||
sync_enabled INTEGER NOT NULL DEFAULT 1,
|
|
||||||
dirty INTEGER NOT NULL DEFAULT 1,
|
|
||||||
next_sync_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_running INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_status TEXT NOT NULL DEFAULT 'idle',
|
|
||||||
sync_error TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_step TEXT NOT NULL DEFAULT '',
|
|
||||||
sync_total INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_done INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_failed INTEGER NOT NULL DEFAULT 0,
|
|
||||||
sync_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_started_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_finished_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_sync_success_at INTEGER NOT NULL DEFAULT 0,
|
|
||||||
last_synced_revision TEXT NOT NULL DEFAULT '',
|
|
||||||
created_at INTEGER NOT NULL,
|
|
||||||
updated_at INTEGER NOT NULL,
|
|
||||||
PRIMARY KEY (repo_id, path),
|
|
||||||
FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO rpm_repo_dirs_new (
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
allow_delete,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
sync_interval_sec,
|
|
||||||
sync_enabled,
|
|
||||||
dirty,
|
|
||||||
next_sync_at,
|
|
||||||
sync_running,
|
|
||||||
sync_status,
|
|
||||||
sync_error,
|
|
||||||
sync_step,
|
|
||||||
sync_total,
|
|
||||||
sync_done,
|
|
||||||
sync_failed,
|
|
||||||
sync_deleted,
|
|
||||||
last_sync_started_at,
|
|
||||||
last_sync_finished_at,
|
|
||||||
last_sync_success_at,
|
|
||||||
last_synced_revision,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
repo_id,
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
0,
|
|
||||||
remote_url,
|
|
||||||
connect_host,
|
|
||||||
host_header,
|
|
||||||
tls_server_name,
|
|
||||||
tls_insecure_skip_verify,
|
|
||||||
sync_interval_sec,
|
|
||||||
sync_enabled,
|
|
||||||
dirty,
|
|
||||||
next_sync_at,
|
|
||||||
sync_running,
|
|
||||||
sync_status,
|
|
||||||
sync_error,
|
|
||||||
sync_step,
|
|
||||||
sync_total,
|
|
||||||
sync_done,
|
|
||||||
sync_failed,
|
|
||||||
sync_deleted,
|
|
||||||
last_sync_started_at,
|
|
||||||
last_sync_finished_at,
|
|
||||||
last_sync_success_at,
|
|
||||||
last_synced_revision,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
FROM rpm_repo_dirs;
|
|
||||||
|
|
||||||
DROP TABLE rpm_repo_dirs;
|
|
||||||
|
|
||||||
ALTER TABLE rpm_repo_dirs_new RENAME TO rpm_repo_dirs;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
PRAGMA foreign_keys = ON;
|
|
||||||
@@ -64,11 +64,42 @@ export default function CommitDetailPage() {
|
|||||||
})
|
})
|
||||||
}, [repoId])
|
}, [repoId])
|
||||||
|
|
||||||
const handleFileDiff = async (file: string) => {
|
const extractFileDiffFromCommitDiff = (raw: string, file: string) => {
|
||||||
if (!repoId || !hash) return
|
const text = (raw || '').replace(/\r\n/g, '\n')
|
||||||
const res = await api.getRepoFileDiff(repoId, hash, file)
|
if (!text) return ''
|
||||||
|
const lines = text.split('\n')
|
||||||
|
const blocks: string[] = []
|
||||||
|
let current: string[] = []
|
||||||
|
let i = 0
|
||||||
|
let line = ''
|
||||||
|
for (i = 0; i < lines.length; i += 1) {
|
||||||
|
line = lines[i]
|
||||||
|
if (line.startsWith('diff --git ')) {
|
||||||
|
if (current.length > 0) {
|
||||||
|
blocks.push(current.join('\n'))
|
||||||
|
}
|
||||||
|
current = [line]
|
||||||
|
} else if (current.length > 0) {
|
||||||
|
current.push(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (current.length > 0) {
|
||||||
|
blocks.push(current.join('\n'))
|
||||||
|
}
|
||||||
|
for (i = 0; i < blocks.length; i += 1) {
|
||||||
|
const block = blocks[i]
|
||||||
|
const header = block.split('\n', 1)[0] || ''
|
||||||
|
if (header.includes(` a/${file} `) || header.endsWith(` a/${file}`) || header.includes(` b/${file} `) || header.endsWith(` b/${file}`)) {
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFileDiff = (file: string) => {
|
||||||
|
const extracted = extractFileDiffFromCommitDiff(diff, file)
|
||||||
setSelectedFile(file)
|
setSelectedFile(file)
|
||||||
setFileDiff(res.diff || '')
|
setFileDiff(extracted)
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderSplitDiff = (raw: string) => {
|
const renderSplitDiff = (raw: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user