mirror of
https://github.com/kopia/kopia.git
synced 2026-01-24 06:18:02 -05:00
This formalizes the concept of a 'UI user' which is a local user that can call APIs the same way that UI does it. The server will now allow access to: - UI user (identified using `--server-username` with password specified using `--server-password' or `--random-password`) - remote users with usersnames/passwords specified in `--htpasswd-file` - remote users defined in the repository using `kopia users add` when `--allow-repository-users` is passed. The UI user only has access to methods specifically designated as such (normally APIs used by the UI + few special ones such as 'shutdown'). Remote users (identified via `user@host`) don't get access to UI APIs. There are some APIs that can be accessed by any authenticated caller (UI or remote): - /api/v1/flush - /api/v1/repo/status - /api/v1/repo/sync - /api/v1/repo/parameters To make this easier to understand in code, refactored server handlers to require specifing what kind of authorization is required at registration time.
55 lines
1.1 KiB
Go
55 lines
1.1 KiB
Go
package server
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/kopia/kopia/internal/clock"
|
|
"github.com/kopia/kopia/repo/object"
|
|
"github.com/kopia/kopia/snapshot/snapshotfs"
|
|
)
|
|
|
|
func (s *Server) handleObjectGet(w http.ResponseWriter, r *http.Request) {
|
|
oidstr := mux.Vars(r)["objectID"]
|
|
|
|
if !requireUIUser(s, r) {
|
|
http.Error(w, "access denied", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
oid, err := object.ParseID(oidstr)
|
|
if err != nil {
|
|
http.Error(w, "invalid object id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
obj, err := s.rep.OpenObject(r.Context(), oid)
|
|
if errors.Is(err, object.ErrObjectNotFound) {
|
|
http.Error(w, "object not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
if snapshotfs.IsDirectoryID(oid) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
}
|
|
|
|
fname := oid.String()
|
|
if p := r.URL.Query().Get("fname"); p != "" {
|
|
fname = p
|
|
w.Header().Set("Content-Disposition", "attachment; filename=\""+p+"\"")
|
|
}
|
|
|
|
mtime := clock.Now()
|
|
|
|
if p := r.URL.Query().Get("mtime"); p != "" {
|
|
if m, err := time.Parse(time.RFC3339Nano, p); err == nil {
|
|
mtime = m
|
|
}
|
|
}
|
|
|
|
http.ServeContent(w, r, fname, mtime, obj)
|
|
}
|