mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 03:01:48 +00:00
Accept forge authorization for deleting a site.
This commit is contained in:
@@ -117,7 +117,7 @@ The authorization flow for content updates (`PUT`, `PATCH`, `DELETE`, `POST` req
|
||||
4. **Wildcard Match (content):** If the method is `POST`, and a `[[wildcard]]` configuration section exists where the suffix of a hostname (compared label-wise) is equal to `[[wildcard]].domain`, and (for `PUT` requests) the body contains a repository URL, and the requested clone URL is a *matching* clone URL, the request is authorized.
|
||||
- **Index repository:** If the request URL is `scheme://<user>.<host>/`, a *matching* clone URL is computed by templating `[[wildcard]].clone-url` with `<user>` and `<project>`, where `<project>` is computed by templating each element of `[[wildcard]].index-repos` with `<user>`, and `[[wildcard]]` is the section where the match occurred.
|
||||
- **Project repository:** If the request URL is `scheme://<user>.<host>/<project>/`, a *matching* clone URL is computed by templating `[[wildcard]].clone-url` with `<user>` and `<project>`, and `[[wildcard]]` is the section where the match occurred.
|
||||
5. **Forge Authorization:** If the method is `PUT` or `PATCH`, and the body contains an archive, and a `[[wildcard]]` configuration section exists where the suffix of a hostname (compared label-wise) is equal to `[[wildcard]].domain`, and `[[wildcard]].authorization` is non-empty, and the request includes a `Forge-Authorization:` header, and the header (when forwarded as `Authorization:`) grants push permissions to a repository at the *matching* clone URL (as defined above) as determined by an API call to the forge, the request is authorized. (This enables publishing a site for a private repository.)
|
||||
5. **Forge Authorization:** If the method is `PUT` or `PATCH` or `DELETE`, and (unless the method is `DELETE`) the body contains an archive, and a `[[wildcard]]` configuration section exists where the suffix of a hostname (compared label-wise) is equal to `[[wildcard]].domain`, and `[[wildcard]].authorization` is non-empty, and the request includes a `Forge-Authorization:` header, and the header (when forwarded as `Authorization:`) grants push permissions to a repository at the *matching* clone URL (as defined above) as determined by an API call to the forge, the request is authorized. (This enables publishing a site for a private repository.)
|
||||
5. **Default Deny:** Otherwise, the request is not authorized.
|
||||
|
||||
The authorization flow for metadata retrieval (`GET` requests with site paths starting with `.git-pages/`) in the following order, with the first of multiple applicable rule taking precedence:
|
||||
|
||||
43
src/auth.go
43
src/auth.go
@@ -390,9 +390,6 @@ func AuthorizeMetadataRetrieval(r *http.Request) (*Authorization, error) {
|
||||
return nil, joinErrors(causes...)
|
||||
}
|
||||
|
||||
// Returns `repoURLs, err` where if `err == nil` then the request is authorized to clone from
|
||||
// any repository URL included in `repoURLs` (by case-insensitive comparison), or any URL at all
|
||||
// if `repoURLs == nil`.
|
||||
func AuthorizeUpdateFromRepository(r *http.Request) (*Authorization, error) {
|
||||
causes := []error{AuthError{http.StatusUnauthorized, "unauthorized"}}
|
||||
|
||||
@@ -643,8 +640,9 @@ func authorizeForgeWithToken(r *http.Request) (*Authorization, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// This will actually be ignored by the caller of AuthorizeUpdateFromArchive,
|
||||
// but we return this information as it makes sense to do contextually here.
|
||||
// This will actually be ignored by the callers of AuthorizeUpdateFromArchive and
|
||||
// AuthorizeDeletion, but we return this information as it makes sense to do
|
||||
// contextually here.
|
||||
return &Authorization{[]string{repoURL}, branch}, nil
|
||||
}
|
||||
}
|
||||
@@ -696,6 +694,41 @@ func AuthorizeUpdateFromArchive(r *http.Request) (*Authorization, error) {
|
||||
return nil, joinErrors(causes...)
|
||||
}
|
||||
|
||||
func AuthorizeDeletion(r *http.Request) (*Authorization, error) {
|
||||
causes := []error{AuthError{http.StatusUnauthorized, "unauthorized"}}
|
||||
|
||||
if err := CheckForbiddenDomain(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auth := authorizeInsecure(r)
|
||||
if auth != nil {
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
auth, err := authorizeDNSChallenge(r)
|
||||
if err != nil && IsUnauthorized(err) {
|
||||
causes = append(causes, err)
|
||||
} else if err != nil { // bad request
|
||||
return nil, err
|
||||
} else {
|
||||
logc.Printf(r.Context(), "auth: DNS challenge: allow *\n")
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
auth, err = authorizeForgeWithToken(r)
|
||||
if err != nil && IsUnauthorized(err) {
|
||||
causes = append(causes, err)
|
||||
} else if err != nil { // bad request
|
||||
return nil, err
|
||||
} else {
|
||||
logc.Printf(r.Context(), "auth: forge token: allow\n")
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
return nil, joinErrors(causes...)
|
||||
}
|
||||
|
||||
func CheckForbiddenDomain(r *http.Request) error {
|
||||
host, err := GetHost(r)
|
||||
if err != nil {
|
||||
|
||||
@@ -661,7 +661,7 @@ func deletePage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = AuthorizeUpdateFromRepository(r)
|
||||
_, err = AuthorizeDeletion(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user