66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
package gonexapp
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// Credentials are what an ExApp needs to call Nextcloud as one user.
|
|
// BaseURL is the Nextcloud instance URL. A trailing slash is tolerated by
|
|
// callers in this package and is removed when they build a URL.
|
|
// AppID, AppVersion, and AAVersion are sent as EX-APP-ID, EX-APP-VERSION,
|
|
// and AA-VERSION. AppSecret and UserID form the AUTHORIZATION-APP-API token.
|
|
type Credentials struct {
|
|
BaseURL string
|
|
AppID string
|
|
AppVersion string
|
|
AAVersion string
|
|
AppSecret string
|
|
UserID string
|
|
}
|
|
|
|
// AuthHeaders returns AppAPI headers for a request to Nextcloud.
|
|
// The set is AA-VERSION, EX-APP-ID, EX-APP-VERSION, AUTHORIZATION-APP-API,
|
|
// and OCS-APIRequest. AUTHORIZATION-APP-API is base64 of UserID, a colon,
|
|
// and AppSecret. The method does not return an error; empty fields are sent as empty.
|
|
func (c Credentials) AuthHeaders() http.Header {
|
|
h := make(http.Header)
|
|
h.Set("AA-VERSION", c.AAVersion)
|
|
h.Set("EX-APP-ID", c.AppID)
|
|
h.Set("EX-APP-VERSION", c.AppVersion)
|
|
token := base64.StdEncoding.EncodeToString([]byte(c.UserID + ":" + c.AppSecret))
|
|
h.Set("AUTHORIZATION-APP-API", token)
|
|
h.Set("OCS-APIRequest", "true")
|
|
return h
|
|
}
|
|
|
|
// WithUser returns a copy whose UserID is userID.
|
|
// The receiver is not modified.
|
|
func (c Credentials) WithUser(userID string) Credentials {
|
|
out := c
|
|
out.UserID = userID
|
|
return out
|
|
}
|
|
|
|
// UserFromRequest reads the requesting user from AUTHORIZATION-APP-API
|
|
// on an inbound ExApp request.
|
|
// It returns an error when the header is missing, is not base64, or contains
|
|
// no user id before the colon.
|
|
func UserFromRequest(r *http.Request) (string, error) {
|
|
raw := r.Header.Get("AUTHORIZATION-APP-API")
|
|
if raw == "" {
|
|
return "", fmt.Errorf("missing AUTHORIZATION-APP-API")
|
|
}
|
|
decoded, err := base64.StdEncoding.DecodeString(raw)
|
|
if err != nil {
|
|
return "", fmt.Errorf("invalid AUTHORIZATION-APP-API: %w", err)
|
|
}
|
|
parts := strings.SplitN(string(decoded), ":", 2)
|
|
if len(parts) < 1 || strings.TrimSpace(parts[0]) == "" {
|
|
return "", fmt.Errorf("AUTHORIZATION-APP-API has no user id")
|
|
}
|
|
return parts[0], nil
|
|
}
|