add package and manifest file uploads (#204)

Add support to manage package imports and generating/editing appmanifest files. 

Closes #93
This commit is contained in:
Victor Vrantchan
2017-06-05 00:27:14 -07:00
committed by GitHub
parent 40ccbefc17
commit d352d6cc95
14 changed files with 532 additions and 11 deletions

97
appstore/appstore.go Normal file
View File

@@ -0,0 +1,97 @@
// package appstore provides an abstraction for uploading files and manifests
// to a repository.
package appstore
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/groob/plist"
"github.com/micromdm/micromdm/appmanifest"
"github.com/pkg/errors"
)
type AppStore interface {
SaveFile(name string, f io.Reader) error
Manifest(name string) (*appmanifest.Manifest, error)
Apps(name string) (map[string]appmanifest.Manifest, error)
}
type Repo struct {
Path string
}
func (r *Repo) SaveFile(name string, f io.Reader) error {
fname := filepath.Join(r.Path, name)
file, err := os.Create(fname)
if err != nil {
return errors.Wrapf(err, "saving file %s", name)
}
defer file.Close()
_, err = io.Copy(file, f)
return err
}
func (r *Repo) Manifest(name string) (*appmanifest.Manifest, error) {
manifestName := name
if !strings.HasSuffix(name, ".plist") {
manifestName = name + ".plist"
}
fname := filepath.Join(r.Path, manifestName)
file, err := os.Open(fname)
if err != nil {
return nil, errors.Wrapf(err, "reading manifest %s", name)
}
defer file.Close()
var m appmanifest.Manifest
if err := plist.NewDecoder(file).Decode(&m); err != nil {
return nil, errors.Wrap(err, "decoding manifest file")
}
return &m, nil
}
func (r *Repo) Apps(name string) (map[string]appmanifest.Manifest, error) {
manifests := make(map[string]appmanifest.Manifest)
if name != "" {
mf, err := os.Open(filepath.Join(r.Path, name))
if err != nil {
return nil, err
}
var m appmanifest.Manifest
if err := plist.NewDecoder(mf).Decode(&m); err != nil {
return nil, err
}
manifests[name] = m
return manifests, nil
}
files, err := ioutil.ReadDir(r.Path)
if err != nil {
return nil, err
}
for _, file := range files {
manifestName := file.Name()
if file.IsDir() || filepath.Ext(manifestName) != ".plist" {
continue
}
mf, err := os.Open(filepath.Join(r.Path, manifestName))
if err != nil {
return nil, err
}
var m appmanifest.Manifest
if err := plist.NewDecoder(mf).Decode(&m); err != nil {
return nil, err
}
manifests[manifestName] = m
}
return manifests, nil
}

View File

@@ -3,6 +3,7 @@ package main
import (
"bytes"
"compress/zlib"
"context"
"encoding/binary"
"flag"
"fmt"
@@ -29,6 +30,7 @@ func (cmd *applyCommand) applyApp(args []string) error {
flHashSize = flagset.Int64("md5size", appmanifest.DefaultMD5Size, "md5 hash size in bytes (optional)")
flSign = flagset.String("sign", "", "sign package before importing, requires specifying a product ID (optional)")
flUpload = flagset.Bool("upload", false, "upload package and/or manifest to micromdm repository.")
)
flagset.Usage = usageFor(flagset, "mdmctl apply app [flags]")
if err := flagset.Parse(args); err != nil {
@@ -98,6 +100,13 @@ Please rebuild the package and re-run the command.
return err
}
if *flUpload {
err := cmd.applysvc.UploadApp(context.TODO(), nameMannifest(f.Name()), &buf, filepath.Base(f.Name()), f)
if err != nil {
return err
}
}
switch *flAppManifest {
case "":
case "-":
@@ -110,6 +119,11 @@ Please rebuild the package and re-run the command.
return nil
}
func nameMannifest(pkgName string) string {
trimmed := strings.TrimSuffix(filepath.Base(pkgName), filepath.Ext(pkgName))
return trimmed + ".plist"
}
func checkDistribution(pkgPath string) (bool, error) {
const (
xarHeaderMagic = 0x78617221
@@ -147,7 +161,15 @@ func checkDistribution(pkgPath string) (bool, error) {
}
func (cmd *applyCommand) serverRepoURL() (string, error) {
serverURL, err := url.Parse(cmd.config.ServerURL)
return repoURL(cmd.config.ServerURL)
}
func pkgURL(repoURL, pkgPath string) string {
return path.Join(repoURL, filepath.Base(pkgPath))
}
func repoURL(server string) (string, error) {
serverURL, err := url.Parse(server)
if err != nil {
return "", err
}
@@ -155,10 +177,6 @@ func (cmd *applyCommand) serverRepoURL() (string, error) {
return serverURL.String(), nil
}
func pkgURL(repoURL, pkgPath string) string {
return path.Join(repoURL, filepath.Base(pkgPath))
}
// replaces .pkg with .plist
func manifestURL(repoURL, pkgPath string) string {
pu := pkgURL(repoURL, pkgPath)

View File

@@ -63,6 +63,8 @@ func (cmd *getCommand) Run(args []string) error {
run = cmd.getBlueprints
case "profiles":
run = cmd.getProfiles
case "apps":
run = cmd.getApps
default:
cmd.Usage()
os.Exit(1)
@@ -84,6 +86,7 @@ Valid resource types:
* dep-account
* dep-profiles
* profiles
* apps
Examples:
# Get a list of devices

62
cmd/mdmctl/get_app.go Normal file
View File

@@ -0,0 +1,62 @@
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"os"
"text/tabwriter"
"github.com/micromdm/micromdm/core/list"
)
type appsTableOutput struct{ w *tabwriter.Writer }
func (out *appsTableOutput) BasicHeader() {
fmt.Fprintf(out.w, "Name\t,ManifestURL\n")
}
func (out *appsTableOutput) BasicFooter() {
out.w.Flush()
}
func (cmd *getCommand) getApps(args []string) error {
flagset := flag.NewFlagSet("apps", flag.ExitOnError)
var (
flNameFilter = flagset.String("name", "", "specify the name of the app to get full details")
flOutputPath = flagset.String("f", "-", "path to save file to. defaults to stdout.")
)
flagset.Usage = usageFor(flagset, "mdmctl get apps [flags]")
if err := flagset.Parse(args); err != nil {
return err
}
ctx := context.Background()
apps, err := cmd.list.ListApplications(ctx, list.ListAppsOption{
FilterName: []string{*flNameFilter},
})
if err != nil {
return err
}
if *flNameFilter != "" && (len(apps) != 0) {
payload := apps[0].Payload
if *flOutputPath == "-" {
fmt.Println(string(payload))
return nil
}
return ioutil.WriteFile(*flOutputPath, payload, 0644)
}
rURL, err := repoURL(cmd.config.ServerURL)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stderr, 0, 4, 2, ' ', 0)
out := appsTableOutput{w}
out.BasicHeader()
defer out.BasicFooter()
for _, a := range apps {
manifestURL := rURL + "/" + a.Name
fmt.Fprintf(out.w, "%s\t%s\n", a.Name, manifestURL)
}
return nil
}

View File

@@ -58,11 +58,23 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
).Endpoint()
}
var uploadAppEndpoint endpoint.Endpoint
{
uploadAppEndpoint = httptransport.NewClient(
"POST",
copyURL(u, "/v1/apps"),
encodeRequestWithToken(token, EncodeUploadAppRequest),
DecodeUploadAppResponse,
opts...,
).Endpoint()
}
return Endpoints{
ApplyBlueprintEndpoint: applyBlueprintEndpoint,
ApplyDEPTokensEndpoint: applyDEPTokensEndpoint,
ApplyProfileEndpoint: applyProfileEndpoint,
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
AppUploadEndpoint: uploadAppEndpoint,
}, nil
}

View File

@@ -2,6 +2,7 @@ package apply
import (
"context"
"io"
"github.com/go-kit/kit/endpoint"
"github.com/micromdm/dep"
@@ -14,6 +15,21 @@ type Endpoints struct {
ApplyDEPTokensEndpoint endpoint.Endpoint
ApplyProfileEndpoint endpoint.Endpoint
DefineDEPProfileEndpoint endpoint.Endpoint
AppUploadEndpoint endpoint.Endpoint
}
func (e Endpoints) UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error {
request := appUploadRequest{
ManifestName: manifestName,
ManifestFile: manifest,
PKGFilename: pkgName,
PKGFile: pkg,
}
resp, err := e.AppUploadEndpoint(ctx, request)
if err != nil {
return err
}
return resp.(appUploadResponse).Err
}
func (e Endpoints) DefineDEPProfile(ctx context.Context, p *dep.Profile) (*dep.ProfileResponse, error) {
@@ -94,6 +110,30 @@ func MakeDefineDEPProfile(svc Service) endpoint.Endpoint {
}
}
func MakeUploadAppEndpiont(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(appUploadRequest)
err = svc.UploadApp(ctx, req.ManifestName, req.ManifestFile, req.PKGFilename, req.PKGFile)
return &appUploadResponse{
Err: err,
}, nil
}
}
type appUploadRequest struct {
ManifestName string
ManifestFile io.Reader
PKGFilename string
PKGFile io.Reader
}
type appUploadResponse struct {
Err error `json:"err,omitempty"`
}
func (r appUploadResponse) error() error { return r.Err }
type blueprintRequest struct {
Blueprint *blueprint.Blueprint `json:"blueprint"`
}

View File

@@ -15,6 +15,7 @@ import (
"github.com/fullsailor/pkcs7"
"github.com/micromdm/dep"
"github.com/micromdm/micromdm/appstore"
"github.com/micromdm/micromdm/blueprint"
"github.com/micromdm/micromdm/deptoken"
"github.com/micromdm/micromdm/profile"
@@ -25,6 +26,7 @@ type Service interface {
ApplyBlueprint(ctx context.Context, bp *blueprint.Blueprint) error
ApplyDEPToken(ctx context.Context, P7MContent []byte) error
ApplyProfile(ctx context.Context, p *profile.Profile) error
UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error
DEPService
}
@@ -35,6 +37,23 @@ type ApplyService struct {
Blueprints *blueprint.DB
Profiles *profile.DB
Tokens *deptoken.DB
Apps appstore.AppStore
}
func (svc *ApplyService) UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error {
if manifestName != "" {
if err := svc.Apps.SaveFile(manifestName, manifest); err != nil {
return err
}
}
if pkgName != "" {
if err := svc.Apps.SaveFile(pkgName, pkg); err != nil {
return err
}
}
return nil
}
func (svc *ApplyService) WatchTokenUpdates(pubsub pubsub.Subscriber) error {

View File

@@ -4,11 +4,13 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/pkg/errors"
)
type HTTPHandlers struct {
@@ -16,6 +18,7 @@ type HTTPHandlers struct {
DEPTokensHandler http.Handler
ProfileHandler http.Handler
DefineDEPProfileHandler http.Handler
AppUploadHandler http.Handler
}
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
@@ -44,6 +47,12 @@ func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptran
encodeResponse,
opts...,
),
AppUploadHandler: httptransport.NewServer(
endpoints.AppUploadEndpoint,
decodeAppUploadRequest,
encodeResponse,
opts...,
),
}
return h
}
@@ -80,6 +89,64 @@ func decodeDEPProfileRequest(ctx context.Context, r *http.Request) (interface{},
return req, nil
}
func decodeAppUploadRequest(ctx context.Context, r *http.Request) (interface{}, error) {
defer r.Body.Close()
appManifestFilename := r.FormValue("app_manifest_filename")
manifestFile, _, err := r.FormFile("app_manifest_filedata")
if err != nil && err != http.ErrMissingFile {
return nil, errors.Wrap(err, "manifest file")
}
pkgFilename := r.FormValue("pkg_name")
pkgFile, _, err := r.FormFile("pkg_filedata")
if err != nil && err != http.ErrMissingFile {
return nil, err
}
return appUploadRequest{
ManifestName: appManifestFilename,
ManifestFile: manifestFile,
PKGFilename: pkgFilename,
PKGFile: pkgFile,
}, nil
}
func EncodeUploadAppRequest(_ context.Context, r *http.Request, request interface{}) error {
req := request.(appUploadRequest)
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
if req.ManifestName != "" {
partManifest, err := writer.CreateFormFile("app_manifest_filedata", req.ManifestName)
if err != nil {
return err
}
_, err = io.Copy(partManifest, req.ManifestFile)
if err != nil {
return errors.Wrap(err, "copying appmanifest file to multipart writer")
}
writer.WriteField("app_manifest_filename", req.ManifestName)
}
if req.PKGFilename != "" {
partPkg, err := writer.CreateFormFile("pkg_filedata", req.PKGFilename)
if err != nil {
return err
}
_, err = io.Copy(partPkg, req.PKGFile)
if err != nil {
return errors.Wrap(err, "copying pkg file to multipart writer")
}
writer.WriteField("pkg_name", req.PKGFilename)
}
if err := writer.Close(); err != nil {
return errors.Wrap(err, "closing multipart writer")
}
r.Header.Set("Content-Type", writer.FormDataContentType())
r.Body = ioutil.NopCloser(body)
return nil
}
type errorWrapper struct {
Error string `json:"error"`
}
@@ -160,3 +227,12 @@ func DecodeDEPProfileResponse(_ context.Context, r *http.Response) (interface{},
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}
func DecodeUploadAppResponse(_ context.Context, r *http.Response) (interface{}, error) {
if r.StatusCode != http.StatusOK {
return nil, errorDecoder(r)
}
var resp appUploadResponse
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}

View File

@@ -0,0 +1,65 @@
package apply
import (
"bytes"
"context"
"io"
"mime/multipart"
"net/http/httptest"
"testing"
)
func TestDecodeUploadRequest(t *testing.T) {
var aFile, bFile bytes.Buffer
aFile.Write([]byte("hello"))
bFile.Write([]byte("world"))
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("app_manifest_filedata", "manifest.plist")
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(part, &aFile)
if err != nil {
t.Fatal(err)
}
writer.WriteField("app_manifest_filename", "manifest.plist")
partPkg, err := writer.CreateFormFile("pkg_filedata", "foo.pkg")
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(partPkg, &bFile)
if err != nil {
t.Fatal(err)
}
writer.WriteField("pkg_name", "hello.pkg")
writer.Close()
req := httptest.NewRequest("POST", "https://mdm.acme.co/", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
request, err := decodeAppUploadRequest(context.Background(), req)
if err != nil {
t.Fatal(err)
}
decoded := request.(appUploadRequest)
if have, want := decoded.ManifestName, "manifest.plist"; have != want {
t.Errorf("have %s, want %s", have, want)
}
if have, want := decoded.PKGFilename, "hello.pkg"; have != want {
t.Errorf("have %s, want %s", have, want)
}
var a, b bytes.Buffer
io.Copy(&a, decoded.ManifestFile)
io.Copy(&b, decoded.PKGFile)
if have, want := a.String(), "hello"; have != want {
t.Errorf("have %s, want %s", have, want)
}
if have, want := b.String(), "world"; have != want {
t.Errorf("have %s, want %s", have, want)
}
}

View File

@@ -90,6 +90,17 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
).Endpoint()
}
var listAppsEndpoint endpoint.Endpoint
{
listAppsEndpoint = httptransport.NewClient(
"GET",
copyURL(u, "/v1/apps"),
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
DecodeListAppsResponse,
opts...,
).Endpoint()
}
return Endpoints{
ListDevicesEndpoint: listDevicesEndpoint,
GetDEPTokensEndpoint: getDEPTokensEndpoint,
@@ -98,6 +109,7 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
GetDEPAccountInfoEndpoint: getDEPAccountInfoEndpoint,
GetDEPDeviceEndpoint: getDEPDeviceDetailsEndpoint,
GetDEPProfileEndpoint: getDEPProfilesEndpoint,
ListAppsEndpont: listAppsEndpoint,
}, nil
}

View File

@@ -19,6 +19,7 @@ type Endpoints struct {
GetDEPAccountInfoEndpoint endpoint.Endpoint
GetDEPDeviceEndpoint endpoint.Endpoint
GetDEPProfileEndpoint endpoint.Endpoint
ListAppsEndpont endpoint.Endpoint
}
func (e Endpoints) ListDevices(ctx context.Context, opts ListDevicesOption) ([]DeviceDTO, error) {
@@ -30,6 +31,15 @@ func (e Endpoints) ListDevices(ctx context.Context, opts ListDevicesOption) ([]D
return response.(devicesResponse).Devices, response.(devicesResponse).Err
}
func (e Endpoints) ListApplications(ctx context.Context, opts ListAppsOption) ([]AppDTO, error) {
request := appListRequest{opts}
response, err := e.ListAppsEndpont(ctx, request.Opts)
if err != nil {
return nil, err
}
return response.(appListResponse).Apps, response.(appListResponse).Err
}
func (e Endpoints) GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byte, error) {
resp, err := e.GetDEPTokensEndpoint(ctx, nil)
if err != nil {
@@ -85,6 +95,17 @@ func MakeListDevicesEndpoint(svc Service) endpoint.Endpoint {
}
}
func MakeListAppsEndpoint(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(appListRequest)
apps, err := svc.ListApplications(ctx, req.Opts)
return appListResponse{
Apps: apps,
Err: err,
}, nil
}
}
func (e Endpoints) GetDEPProfile(ctx context.Context, uuid string) (*dep.Profile, error) {
request := depProfileRequest{UUID: uuid}
response, err := e.GetDEPProfileEndpoint(ctx, request)
@@ -213,3 +234,19 @@ type depProfileResponse struct {
}
func (r depProfileResponse) error() error { return r.Err }
type appListRequest struct {
Opts ListAppsOption
}
type AppDTO struct {
Name string `json:"name"`
Payload []byte `json:"payload,omitempty"`
}
type appListResponse struct {
Apps []AppDTO `json:"apps,omitempty"`
Err error `json:"err,omitempty"`
}
func (r appListResponse) error() error { return r.Err }

View File

@@ -6,12 +6,15 @@ import (
"log"
"sync"
"github.com/groob/plist"
"github.com/micromdm/dep"
"github.com/micromdm/micromdm/appstore"
"github.com/micromdm/micromdm/blueprint"
"github.com/micromdm/micromdm/deptoken"
"github.com/micromdm/micromdm/device"
"github.com/micromdm/micromdm/profile"
"github.com/micromdm/micromdm/pubsub"
"github.com/pkg/errors"
)
type ListDevicesOption struct {
@@ -30,11 +33,16 @@ type GetProfilesOption struct {
Identifier string `json:"id"`
}
type ListAppsOption struct {
FilterName []string `json:"filter_name"`
}
type Service interface {
ListDevices(ctx context.Context, opt ListDevicesOption) ([]DeviceDTO, error)
GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byte, error)
GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]blueprint.Blueprint, error)
GetProfiles(ctx context.Context, opt GetProfilesOption) ([]profile.Profile, error)
ListApplications(ctx context.Context, opt ListAppsOption) ([]AppDTO, error)
DEPService
}
@@ -46,6 +54,30 @@ type ListService struct {
Blueprints *blueprint.DB
Profiles *profile.DB
Tokens *deptoken.DB
Apps appstore.AppStore
}
func (svc *ListService) ListApplications(ctx context.Context, opts ListAppsOption) ([]AppDTO, error) {
var filter string
if len(opts.FilterName) == 1 {
filter = opts.FilterName[0]
}
apps, err := svc.Apps.Apps(filter)
if err != nil {
return nil, err
}
var appList []AppDTO
for name, app := range apps {
payload, err := plist.MarshalIndent(&app, " ")
if err != nil {
return nil, errors.Wrap(err, "create dto payload")
}
appList = append(appList, AppDTO{
Name: name,
Payload: payload,
})
}
return appList, nil
}
func (svc *ListService) WatchTokenUpdates(pubsub pubsub.Subscriber) error {

View File

@@ -17,8 +17,9 @@ type HTTPHandlers struct {
GetBlueprintsHandler http.Handler
GetProfilesHandler http.Handler
GetDEPAccountInfoHandler http.Handler
GetDEPProfileHander http.Handler
GetDEPProfileHandler http.Handler
GetDEPDeviceDetailsHandler http.Handler
ListAppsHandler http.Handler
}
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
@@ -56,12 +57,18 @@ func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptran
encodeResponse,
opts...,
),
GetDEPProfileHander: httptransport.NewServer(
GetDEPProfileHandler: httptransport.NewServer(
endpoints.GetDEPProfileEndpoint,
decodeDEPProfileRequest,
encodeResponse,
opts...,
),
ListAppsHandler: httptransport.NewServer(
endpoints.ListAppsEndpont,
decodeListAppsRequest,
encodeResponse,
opts...,
),
}
return h
}
@@ -119,6 +126,14 @@ func decodeDEPProfileRequest(ctx context.Context, r *http.Request) (interface{},
return request, nil
}
func decodeListAppsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
var request appListRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
return nil, err
}
return request, nil
}
func errorDecoder(r *http.Response) error {
var w errorWrapper
if err := json.NewDecoder(r.Body).Decode(&w); err != nil {
@@ -226,3 +241,12 @@ func DecodeDEPProfileResponse(_ context.Context, r *http.Response) (interface{},
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}
func DecodeListAppsResponse(_ context.Context, r *http.Response) (interface{}, error) {
if r.StatusCode != http.StatusOK {
return nil, errorDecoder(r)
}
var resp appListResponse
err := json.NewDecoder(r.Body).Decode(&resp)
return resp, err
}

View File

@@ -40,6 +40,7 @@ import (
boltdepot "github.com/micromdm/scep/depot/bolt"
scep "github.com/micromdm/scep/server"
"github.com/micromdm/micromdm/appstore"
"github.com/micromdm/micromdm/blueprint"
"github.com/micromdm/micromdm/checkin"
"github.com/micromdm/micromdm/command"
@@ -213,9 +214,17 @@ func serve(args []string) error {
stdlog.Fatalf("creating DEP client %s\n", err)
}
tokenDB := &deptoken.DB{DB: sm.db, Publisher: sm.pubclient}
appDB := &appstore.Repo{Path: *flRepoPath}
var listsvc list.Service
{
l := &list.ListService{DEPClient: dc, Devices: devDB, Tokens: tokenDB, Blueprints: bpDB, Profiles: profDB}
l := &list.ListService{
DEPClient: dc,
Devices: devDB,
Tokens: tokenDB,
Blueprints: bpDB,
Profiles: profDB,
Apps: appDB,
}
listsvc = l
if err := l.WatchTokenUpdates(sm.pubclient); err != nil {
@@ -235,11 +244,18 @@ func serve(args []string) error {
GetDEPAccountInfoEndpoint: list.MakeGetDEPAccountInfoEndpoint(listsvc),
GetDEPProfileEndpoint: list.MakeGetDEPProfileEndpoint(listsvc),
GetDEPDeviceEndpoint: list.MakeGetDEPDeviceDetailsEndpoint(listsvc),
ListAppsEndpont: list.MakeListAppsEndpoint(listsvc),
}
var applysvc apply.Service
{
l := &apply.ApplyService{DEPClient: dc, Blueprints: bpDB, Tokens: tokenDB, Profiles: profDB}
l := &apply.ApplyService{
DEPClient: dc,
Blueprints: bpDB,
Tokens: tokenDB,
Profiles: profDB,
Apps: appDB,
}
applysvc = l
if err := l.WatchTokenUpdates(sm.pubclient); err != nil {
stdlog.Fatal(err)
@@ -261,11 +277,17 @@ func serve(args []string) error {
defineDEPProfileEndpoint = apply.MakeDefineDEPProfile(applysvc)
}
var appUploadEndpoint endpoint.Endpoint
{
appUploadEndpoint = apply.MakeUploadAppEndpiont(applysvc)
}
applyEndpoints := apply.Endpoints{
ApplyBlueprintEndpoint: applyBlueprintEndpoint,
ApplyDEPTokensEndpoint: apply.MakeApplyDEPTokensEndpoint(applysvc),
ApplyProfileEndpoint: applyProfileEndpoint,
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
AppUploadEndpoint: appUploadEndpoint,
}
applyAPIHandlers := apply.MakeHTTPHandlers(ctx, applyEndpoints, connectOpts...)
@@ -306,8 +328,10 @@ func serve(args []string) error {
r.Handle("/v1/profiles", apiAuthMiddleware(*flAPIKey, removeAPIHandlers.ProfileHandler)).Methods("DELETE")
r.Handle("/v1/dep/devices", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPDeviceDetailsHandler)).Methods("GET")
r.Handle("/v1/dep/account", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPAccountInfoHandler)).Methods("GET")
r.Handle("/v1/dep/profiles", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPProfileHander)).Methods("GET")
r.Handle("/v1/dep/profiles", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPProfileHandler)).Methods("GET")
r.Handle("/v1/dep/profiles", apiAuthMiddleware(*flAPIKey, applyAPIHandlers.DefineDEPProfileHandler)).Methods("POST")
r.Handle("/v1/apps", apiAuthMiddleware(*flAPIKey, applyAPIHandlers.AppUploadHandler)).Methods("POST")
r.Handle("/v1/apps", apiAuthMiddleware(*flAPIKey, listAPIHandlers.ListAppsHandler)).Methods("GET")
}
if *flRepoPath != "" {