GitRoot

craft your forge, build your project, grow your community freely
 1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
 2//
 3// SPDX-License-Identifier: EUPL-1.2
 4
 5package plugin
 6
 7import (
 8	"errors"
 9	"fmt"
10	"io/fs"
11	"os"
12	"slices"
13	"strings"
14
15	"github.com/go-git/go-git/v5/plumbing"
16	pluginLib "gitroot.dev/libs/golang/plugin/model"
17)
18
19func checkBranch(pluginRun PluginRun, branch plumbing.ReferenceName) bool {
20	if len(pluginRun.Branch) == 0 {
21		return false
22	}
23
24	isAuthorized := true
25	for _, b := range pluginRun.Branch {
26		if b == "*" {
27			isAuthorized = true
28			break
29		}
30		if branch.Short() != b {
31			isAuthorized = false
32		}
33	}
34
35	//negate check
36	for _, b := range pluginRun.Branch {
37		if strings.HasPrefix(b, "!") && strings.TrimPrefix(b, "!") == branch.Short() {
38			isAuthorized = false
39		}
40	}
41
42	return isAuthorized
43}
44
45var ErrCantAdd = errors.New("plugin try to add new file but can't")
46var ErrCantMod = errors.New("plugin try to mod file but can't")
47
48func checkWrite(pluginWriteRight []PluginWriteRight, f fs.FS, path string) (bool, error) {
49	canAdd := slices.ContainsFunc(pluginWriteRight, func(pwr PluginWriteRight) bool {
50		return slices.Contains(pwr.Can, pluginLib.PluginWriteRightCanAdd) && pwr.glob.Match(path)
51	})
52	canMod := slices.ContainsFunc(pluginWriteRight, func(pwr PluginWriteRight) bool {
53		return slices.Contains(pwr.Can, pluginLib.PluginWriteRightCanMod) && pwr.glob.Match(path)
54	})
55	if !canAdd && !canMod {
56		return false, nil
57	}
58	if !canAdd || !canMod {
59		_, err := fs.Stat(f, path)
60		if errors.Is(err, os.ErrNotExist) && !canAdd {
61			return false, ErrCantAdd
62		} else if err == nil && !canMod {
63			return false, ErrCantMod
64		} else if err != nil && !errors.Is(err, os.ErrNotExist) {
65			return false, err
66		}
67	}
68	return true, nil
69}
70
71func checkExec(pluginWriteRight []PluginExecRight, execs []pluginLib.Exec) (bool, error) {
72	for _, per := range pluginWriteRight {
73		notAuthorized := slices.IndexFunc(execs, func(exec pluginLib.Exec) bool {
74			cmd := fmt.Sprintf("%s %s", exec.Cmd, strings.Join(exec.Args, " "))
75			return per.regexp.Match([]byte(cmd))
76		})
77		if notAuthorized > -1 {
78			return false, fmt.Errorf("not authorized %s", execs[notAuthorized].Cmd)
79		}
80	}
81	return true, nil
82}