e89e3102edf8ec2168e0ac0eaf5636dc0f0b35e5
- Author
- Kieran Klukas <kieran@dunkirk.sh>
- Committer
- Kieran Klukas <kieran@dunkirk.sh>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/pkg/web/git_lfs.go b/pkg/web/git_lfs.go
2index 19d08ba03b56d0e6b438a49028bc0d45f87d1aea..6230aa7ef627585488b20c0e17e99efb34e30063 100644
3--- a/pkg/web/git_lfs.go
4+++ b/pkg/web/git_lfs.go
5@@ -7,7 +7,6 @@ import (
6 "io"
7 "io/fs"
8 "net/http"
9- "net/url"
10 "path"
11 "path/filepath"
12 "strconv"
13@@ -17,7 +16,6 @@ import (
14 "github.com/charmbracelet/soft-serve/pkg/access"
15 "github.com/charmbracelet/soft-serve/pkg/config"
16 "github.com/charmbracelet/soft-serve/pkg/db"
17- "github.com/charmbracelet/soft-serve/pkg/db/models"
18 "github.com/charmbracelet/soft-serve/pkg/lfs"
19 "github.com/charmbracelet/soft-serve/pkg/proto"
20 "github.com/charmbracelet/soft-serve/pkg/storage"
21@@ -460,512 +458,6 @@ func serviceLfsBasicVerify(w http.ResponseWriter, r *http.Request) {
22 }
23 }
24
25-func serviceLfsLocks(w http.ResponseWriter, r *http.Request) {
26- switch r.Method {
27- case http.MethodGet:
28- serviceLfsLocksGet(w, r)
29- case http.MethodPost:
30- serviceLfsLocksCreate(w, r)
31- default:
32- renderMethodNotAllowed(w, r)
33- }
34-}
35-
36-// POST: /<repo>.git/info/lfs/objects/locks
37-func serviceLfsLocksCreate(w http.ResponseWriter, r *http.Request) {
38- if !isLfs(r) {
39- renderNotAcceptable(w)
40- return
41- }
42-
43- ctx := r.Context()
44- logger := log.FromContext(ctx).WithPrefix("http.lfs-locks")
45-
46- // Checked in withAccess too. Repeated here so a routing or middleware
47- // mistake cannot turn into an unauthorized lock.
48- if access.FromContext(ctx) < access.ReadWriteAccess {
49- askCredentials(w, r)
50- renderJSON(w, http.StatusForbidden, lfs.ErrorResponse{
51- Message: "write access required",
52- })
53- return
54- }
55-
56- var req lfs.LockCreateRequest
57- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
58- logger.Error("error decoding json", "err", err)
59- renderJSON(w, http.StatusBadRequest, lfs.ErrorResponse{
60- Message: "invalid request: " + err.Error(),
61- })
62- return
63- }
64-
65- repo, ok := lfsRepository(w, r)
66- if !ok {
67- return
68- }
69-
70- user := proto.UserFromContext(ctx)
71- if user == nil {
72- logger.Error("error getting user from context")
73- renderJSON(w, http.StatusNotFound, lfs.ErrorResponse{
74- Message: "user not found",
75- })
76- return
77- }
78-
79- dbx := db.FromContext(ctx)
80- datastore := store.FromContext(ctx)
81- if err := datastore.CreateLFSLockForUser(ctx, dbx, repo.ID(), user.ID(), req.Path, req.Ref.Name); err != nil {
82- err = db.WrapError(err)
83- if errors.Is(err, db.ErrDuplicateKey) {
84- errResp := lfs.LockResponse{
85- ErrorResponse: lfs.ErrorResponse{
86- Message: "lock already exists",
87- },
88- }
89- lock, err := datastore.GetLFSLockForUserPath(ctx, dbx, repo.ID(), user.ID(), req.Path)
90- if err == nil {
91- errResp.Lock = lfs.Lock{
92- ID: strconv.FormatInt(lock.ID, 10),
93- Path: lock.Path,
94- LockedAt: lock.CreatedAt,
95- }
96- lockOwner := lfs.Owner{
97- Name: user.Username(),
98- }
99- if lock.UserID != user.ID() {
100- owner, err := datastore.GetUserByID(ctx, dbx, lock.UserID)
101- if err != nil {
102- logger.Error("error getting lock owner", "err", err)
103- renderJSON(w, http.StatusInternalServerError, lfs.ErrorResponse{
104- Message: "internal server error",
105diff --git a/pkg/web/git_lfs_locks.go b/pkg/web/git_lfs_locks.go
106new file mode 100644
107index 0000000000000000000000000000000000000000..c8c41d22939c821b0aade4769fd13b447b702d50
108--- /dev/null
109+++ b/pkg/web/git_lfs_locks.go
110@@ -0,0 +1,525 @@
111+package web
112+
113+import (
114+ "encoding/json"
115+ "errors"
116+ "net/http"
117+ "net/url"
118+ "strconv"
119+ "strings"
120+
121+ "charm.land/log/v2"
122+ "github.com/charmbracelet/soft-serve/pkg/access"
123+ "github.com/charmbracelet/soft-serve/pkg/db"
124+ "github.com/charmbracelet/soft-serve/pkg/db/models"
125+ "github.com/charmbracelet/soft-serve/pkg/lfs"
126+ "github.com/charmbracelet/soft-serve/pkg/proto"
127+ "github.com/charmbracelet/soft-serve/pkg/store"
128+ "github.com/gorilla/mux"
129+)
130+
131+func serviceLfsLocks(w http.ResponseWriter, r *http.Request) {
132+ switch r.Method {
133+ case http.MethodGet:
134+ serviceLfsLocksGet(w, r)
135+ case http.MethodPost:
136+ serviceLfsLocksCreate(w, r)
137+ default:
138+ renderMethodNotAllowed(w, r)
139+ }
140+}
141+
142+// POST: /<repo>.git/info/lfs/objects/locks
143+func serviceLfsLocksCreate(w http.ResponseWriter, r *http.Request) {
144+ if !isLfs(r) {
145+ renderNotAcceptable(w)
146+ return
147+ }
148+
149+ ctx := r.Context()
150+ logger := log.FromContext(ctx).WithPrefix("http.lfs-locks")
151+
152+ // Checked in withAccess too. Repeated here so a routing or middleware
153+ // mistake cannot turn into an unauthorized lock.
154+ if access.FromContext(ctx) < access.ReadWriteAccess {
155+ askCredentials(w, r)
156+ renderJSON(w, http.StatusForbidden, lfs.ErrorResponse{
157+ Message: "write access required",
158+ })
159+ return
160+ }
161+
162+ var req lfs.LockCreateRequest
163+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
164+ logger.Error("error decoding json", "err", err)
165+ renderJSON(w, http.StatusBadRequest, lfs.ErrorResponse{
166+ Message: "invalid request: " + err.Error(),
167+ })
168+ return
169+ }
170+
171+ repo, ok := lfsRepository(w, r)
172+ if !ok {
173+ return
174+ }
175+
176+ user := proto.UserFromContext(ctx)
177+ if user == nil {
178+ logger.Error("error getting user from context")
179+ renderJSON(w, http.StatusNotFound, lfs.ErrorResponse{
180+ Message: "user not found",
181+ })
182+ return
183+ }
184+
185+ dbx := db.FromContext(ctx)
186+ datastore := store.FromContext(ctx)
187+ if err := datastore.CreateLFSLockForUser(ctx, dbx, repo.ID(), user.ID(), req.Path, req.Ref.Name); err != nil {
188+ err = db.WrapError(err)
189+ if errors.Is(err, db.ErrDuplicateKey) {
190+ errResp := lfs.LockResponse{
191+ ErrorResponse: lfs.ErrorResponse{
192+ Message: "lock already exists",
193+ },
194+ }
195+ lock, err := datastore.GetLFSLockForUserPath(ctx, dbx, repo.ID(), user.ID(), req.Path)
196+ if err == nil {
197+ errResp.Lock = lfs.Lock{
198+ ID: strconv.FormatInt(lock.ID, 10),
199+ Path: lock.Path,
200+ LockedAt: lock.CreatedAt,
201+ }
202+ lockOwner := lfs.Owner{
203+ Name: user.Username(),
204+ }
205+ if lock.UserID != user.ID() {
206+ owner, err := datastore.GetUserByID(ctx, dbx, lock.UserID)
207+ if err != nil {
208+ logger.Error("error getting lock owner", "err", err)
209+ renderJSON(w, http.StatusInternalServerError, lfs.ErrorResponse{