mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-11 12:15:34 +08:00
@@ -63,7 +63,7 @@ func (cmd *applyCommand) applyUser(args []string) error {
|
||||
manifest.PasswordHash = hashPlist
|
||||
}
|
||||
|
||||
usr, err := cmd.applysvc.ApplyUser(context.TODO(), manifest)
|
||||
usr, err := cmd.usersvc.ApplyUser(context.TODO(), manifest)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "apply user with mdmctl")
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@ import (
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/api/server/list"
|
||||
)
|
||||
|
||||
type usersTableOutput struct{ w *tabwriter.Writer }
|
||||
@@ -34,7 +33,7 @@ func (cmd *getCommand) getUsers(args []string) error {
|
||||
out.BasicHeader()
|
||||
defer out.BasicFooter()
|
||||
|
||||
users, err := cmd.list.ListUsers(context.TODO(), list.ListUsersOption{})
|
||||
users, err := cmd.usersvc.ListUsers(context.TODO(), user.ListUsersOption{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "list users")
|
||||
}
|
||||
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
"github.com/micromdm/micromdm/platform/remove"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type remoteServices struct {
|
||||
profilesvc profile.Service
|
||||
blueprintsvc blueprint.Service
|
||||
blocksvc remove.Service
|
||||
usersvc user.Service
|
||||
applysvc apply.Service
|
||||
list list.Service
|
||||
}
|
||||
@@ -46,6 +48,13 @@ func setupClient(logger log.Logger) (*remoteServices, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
usersvc, err := user.NewHTTPClient(
|
||||
cfg.ServerURL, cfg.APIToken, logger,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
applysvc, err := apply.NewClient(
|
||||
cfg.ServerURL, logger, cfg.APIToken,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
@@ -64,6 +73,7 @@ func setupClient(logger log.Logger) (*remoteServices, error) {
|
||||
profilesvc: profilesvc,
|
||||
blueprintsvc: blueprintsvc,
|
||||
blocksvc: blocksvc,
|
||||
usersvc: usersvc,
|
||||
applysvc: applysvc,
|
||||
list: listsvc,
|
||||
}, nil
|
||||
|
||||
@@ -61,6 +61,7 @@ import (
|
||||
block "github.com/micromdm/micromdm/platform/remove"
|
||||
blockbuiltin "github.com/micromdm/micromdm/platform/remove/builtin"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
userbuiltin "github.com/micromdm/micromdm/platform/user/builtin"
|
||||
"github.com/micromdm/micromdm/workflow/webhook"
|
||||
)
|
||||
|
||||
@@ -172,7 +173,7 @@ func serve(args []string) error {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
|
||||
userDB, err := user.NewDB(sm.db, sm.pubclient, log.With(logger, "component", "user db"))
|
||||
userDB, err := userbuiltin.NewDB(sm.db, sm.pubclient, log.With(logger, "component", "user db"))
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
@@ -284,8 +285,15 @@ func serve(args []string) error {
|
||||
}
|
||||
|
||||
blueprintEndpoints := blueprint.MakeServerEndpoints(blueprintsvc)
|
||||
|
||||
blockEndpoints := block.MakeServerEndpoints(removeService)
|
||||
|
||||
var usersvc user.Service
|
||||
{
|
||||
usersvc = user.New(userDB)
|
||||
}
|
||||
|
||||
userEndpoints := user.MakeServerEndpoints(usersvc)
|
||||
|
||||
var listsvc list.Service
|
||||
{
|
||||
l := &list.ListService{
|
||||
@@ -293,7 +301,6 @@ func serve(args []string) error {
|
||||
Devices: devDB,
|
||||
Tokens: tokenDB,
|
||||
Apps: appDB,
|
||||
Users: userDB,
|
||||
}
|
||||
listsvc = l
|
||||
|
||||
@@ -313,7 +320,6 @@ func serve(args []string) error {
|
||||
GetDEPProfileEndpoint: list.MakeGetDEPProfileEndpoint(listsvc),
|
||||
GetDEPDeviceEndpoint: list.MakeGetDEPDeviceDetailsEndpoint(listsvc),
|
||||
ListAppsEndpont: list.MakeListAppsEndpoint(listsvc),
|
||||
ListUserEndpoint: list.MakeListUsersEndpoint(listsvc),
|
||||
}
|
||||
|
||||
var applysvc apply.Service
|
||||
@@ -322,7 +328,6 @@ func serve(args []string) error {
|
||||
DEPClient: dc,
|
||||
Tokens: tokenDB,
|
||||
Apps: appDB,
|
||||
Users: userDB,
|
||||
}
|
||||
applysvc = l
|
||||
if err := l.WatchTokenUpdates(sm.pubclient); err != nil {
|
||||
@@ -340,16 +345,10 @@ func serve(args []string) error {
|
||||
appUploadEndpoint = apply.MakeUploadAppEndpiont(applysvc)
|
||||
}
|
||||
|
||||
var applyUserEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyUserEndpoint = apply.MakeApplyUserEndpoint(applysvc)
|
||||
}
|
||||
|
||||
applyEndpoints := apply.Endpoints{
|
||||
ApplyDEPTokensEndpoint: apply.MakeApplyDEPTokensEndpoint(applysvc),
|
||||
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
|
||||
AppUploadEndpoint: appUploadEndpoint,
|
||||
ApplyUserEndpoint: applyUserEndpoint,
|
||||
}
|
||||
|
||||
applyAPIHandlers := apply.MakeHTTPHandlers(ctx, applyEndpoints, connectOpts...)
|
||||
@@ -375,11 +374,13 @@ func serve(args []string) error {
|
||||
profilesHandler := profile.MakeHTTPHandler(profileEndpoints, logger)
|
||||
blueprintsHandler := blueprint.MakeHTTPHandler(blueprintEndpoints, logger)
|
||||
blockhandler := block.MakeHTTPHandler(blockEndpoints, logger)
|
||||
userHandler := user.MakeHTTPHandler(userEndpoints, logger)
|
||||
|
||||
// API commands. Only handled if the user provides an api key.
|
||||
if *flAPIKey != "" {
|
||||
r.Handle("/v1/profiles", apiAuthMiddleware(*flAPIKey, profilesHandler))
|
||||
r.Handle("/v1/blueprints", apiAuthMiddleware(*flAPIKey, blueprintsHandler))
|
||||
r.Handle("/v1/users", apiAuthMiddleware(*flAPIKey, userHandler))
|
||||
r.Handle("/v1/devices/{udid}/block", apiAuthMiddleware(*flAPIKey, blockhandler))
|
||||
r.Handle("/v1/devices/{udid}/unblock", apiAuthMiddleware(*flAPIKey, blockhandler))
|
||||
r.Handle("/push/{udid}", apiAuthMiddleware(*flAPIKey, pushHandlers.PushHandler))
|
||||
@@ -393,8 +394,6 @@ func serve(args []string) error {
|
||||
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")
|
||||
r.Handle("/v1/users", apiAuthMiddleware(*flAPIKey, applyAPIHandlers.ApplyUserhandler)).Methods("PUT")
|
||||
r.Handle("/v1/users", apiAuthMiddleware(*flAPIKey, listAPIHandlers.ListUsersHander)).Methods("GET")
|
||||
r.Handle("/v1/config/certificate", apiAuthMiddleware(*flAPIKey, configHandlers.SavePushCertificateHandler)).Methods("PUT")
|
||||
}
|
||||
|
||||
|
||||
@@ -49,22 +49,10 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var applyUserEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyUserEndpoint = httptransport.NewClient(
|
||||
"PUT",
|
||||
copyURL(u, "/v1/users"),
|
||||
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
|
||||
DecodeApplyUserResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
ApplyDEPTokensEndpoint: applyDEPTokensEndpoint,
|
||||
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
|
||||
AppUploadEndpoint: uploadAppEndpoint,
|
||||
ApplyUserEndpoint: applyUserEndpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,27 +6,12 @@ import (
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/micromdm/dep"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
ApplyDEPTokensEndpoint endpoint.Endpoint
|
||||
DefineDEPProfileEndpoint endpoint.Endpoint
|
||||
AppUploadEndpoint endpoint.Endpoint
|
||||
ApplyUserEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
func (e Endpoints) ApplyUser(ctx context.Context, u user.User) (*user.User, error) {
|
||||
request := applyUserRequest{
|
||||
User: u,
|
||||
}
|
||||
resp, err := e.ApplyUserEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usr := resp.(applyUserResponse).User
|
||||
return &usr, resp.(applyUserResponse).Err
|
||||
}
|
||||
|
||||
func (e Endpoints) UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error {
|
||||
@@ -83,17 +68,6 @@ func MakeDefineDEPProfile(svc Service) endpoint.Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeApplyUserEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(applyUserRequest)
|
||||
u, err := svc.ApplyUser(ctx, req.User)
|
||||
return applyUserResponse{
|
||||
User: *u,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeUploadAppEndpiont(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(appUploadRequest)
|
||||
@@ -135,14 +109,3 @@ type depProfileResponse struct {
|
||||
}
|
||||
|
||||
func (r *depProfileResponse) error() error { return r.Err }
|
||||
|
||||
type applyUserRequest struct {
|
||||
User user.User `json:"user"`
|
||||
}
|
||||
|
||||
type applyUserResponse struct {
|
||||
Err error `json:"err"`
|
||||
User user.User `json:"user"`
|
||||
}
|
||||
|
||||
func (r applyUserResponse) error() error { return r.Err }
|
||||
|
||||
@@ -14,18 +14,15 @@ import (
|
||||
|
||||
"github.com/fullsailor/pkcs7"
|
||||
"github.com/micromdm/dep"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/appstore"
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
ApplyDEPToken(ctx context.Context, P7MContent []byte) error
|
||||
UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error
|
||||
ApplyUser(ctx context.Context, u user.User) (*user.User, error)
|
||||
DEPService
|
||||
}
|
||||
|
||||
@@ -35,20 +32,6 @@ type ApplyService struct {
|
||||
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
}
|
||||
|
||||
func (svc *ApplyService) ApplyUser(ctx context.Context, u user.User) (*user.User, error) {
|
||||
toSave := &u
|
||||
if u.UUID == "" { //newUser
|
||||
usr, err := user.NewFromRequest(u)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create user from request")
|
||||
}
|
||||
toSave = usr
|
||||
}
|
||||
err := svc.Users.Save(toSave)
|
||||
return toSave, errors.Wrap(err, "apply user")
|
||||
}
|
||||
|
||||
func (svc *ApplyService) UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error {
|
||||
|
||||
@@ -17,7 +17,6 @@ type HTTPHandlers struct {
|
||||
DEPTokensHandler http.Handler
|
||||
DefineDEPProfileHandler http.Handler
|
||||
AppUploadHandler http.Handler
|
||||
ApplyUserhandler http.Handler
|
||||
}
|
||||
|
||||
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
|
||||
@@ -40,12 +39,6 @@ func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptran
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
ApplyUserhandler: httptransport.NewServer(
|
||||
endpoints.ApplyUserEndpoint,
|
||||
decodeUserRequest,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -87,15 +80,6 @@ func decodeAppUploadRequest(ctx context.Context, r *http.Request) (interface{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req applyUserRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(err, "decode user request")
|
||||
}
|
||||
defer r.Body.Close()
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func EncodeUploadAppRequest(_ context.Context, r *http.Request, request interface{}) error {
|
||||
req := request.(appUploadRequest)
|
||||
body := new(bytes.Buffer)
|
||||
@@ -204,12 +188,3 @@ func DecodeUploadAppResponse(_ context.Context, r *http.Response) (interface{},
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeApplyUserResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp applyUserResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -81,17 +81,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var listUsersEndpoint endpoint.Endpoint
|
||||
{
|
||||
listUsersEndpoint = httptransport.NewClient(
|
||||
"GET",
|
||||
copyURL(u, "/v1/users"),
|
||||
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
|
||||
DecodeListUsersResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
ListDevicesEndpoint: listDevicesEndpoint,
|
||||
GetDEPTokensEndpoint: getDEPTokensEndpoint,
|
||||
@@ -99,7 +88,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
GetDEPDeviceEndpoint: getDEPDeviceDetailsEndpoint,
|
||||
GetDEPProfileEndpoint: getDEPProfilesEndpoint,
|
||||
ListAppsEndpont: listAppsEndpoint,
|
||||
ListUserEndpoint: listUsersEndpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/micromdm/dep"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
@@ -18,16 +17,6 @@ type Endpoints struct {
|
||||
GetDEPDeviceEndpoint endpoint.Endpoint
|
||||
GetDEPProfileEndpoint endpoint.Endpoint
|
||||
ListAppsEndpont endpoint.Endpoint
|
||||
ListUserEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
func (e Endpoints) ListUsers(ctx context.Context, opts ListUsersOption) ([]user.User, error) {
|
||||
request := userRequest{opts}
|
||||
response, err := e.ListUserEndpoint(ctx, request.Opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.(userResponse).Users, response.(userResponse).Err
|
||||
}
|
||||
|
||||
func (e Endpoints) ListDevices(ctx context.Context, opts ListDevicesOption) ([]DeviceDTO, error) {
|
||||
@@ -74,17 +63,6 @@ func (e Endpoints) GetDEPDevice(ctx context.Context, serials []string) (*dep.Dev
|
||||
return response.(depDeviceDetailsResponse).DeviceDetailsResponse, response.(depDeviceDetailsResponse).Err
|
||||
}
|
||||
|
||||
func MakeListUsersEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(userRequest)
|
||||
dto, err := svc.ListUsers(ctx, req.Opts)
|
||||
return userResponse{
|
||||
Users: dto,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeListDevicesEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(devicesRequest)
|
||||
@@ -157,14 +135,6 @@ type DeviceDTO struct {
|
||||
LastSeen time.Time `json:"last_seen"`
|
||||
}
|
||||
|
||||
type userRequest struct{ Opts ListUsersOption }
|
||||
type userResponse struct {
|
||||
Users []user.User `json:"users"`
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r userResponse) error() error { return r.Err }
|
||||
|
||||
type devicesRequest struct{ Opts ListDevicesOption }
|
||||
type devicesResponse struct {
|
||||
Devices []DeviceDTO `json:"devices"`
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/device"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type ListDevicesOption struct {
|
||||
@@ -25,21 +24,12 @@ type ListDevicesOption struct {
|
||||
FilterUDID []string
|
||||
}
|
||||
|
||||
type ListUsersOption struct {
|
||||
Page int
|
||||
PerPage int
|
||||
|
||||
FilterUserID []string
|
||||
FilterUDID []string
|
||||
}
|
||||
|
||||
type ListAppsOption struct {
|
||||
FilterName []string `json:"filter_name"`
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
ListDevices(ctx context.Context, opt ListDevicesOption) ([]DeviceDTO, error)
|
||||
ListUsers(ctx context.Context, opt ListUsersOption) ([]user.User, error)
|
||||
GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byte, error)
|
||||
ListApplications(ctx context.Context, opt ListAppsOption) ([]AppDTO, error)
|
||||
DEPService
|
||||
@@ -52,7 +42,6 @@ type ListService struct {
|
||||
Devices *device.DB
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
}
|
||||
|
||||
func (svc *ListService) ListApplications(ctx context.Context, opts ListAppsOption) ([]AppDTO, error) {
|
||||
@@ -124,11 +113,6 @@ func (svc *ListService) ListDevices(ctx context.Context, opt ListDevicesOption)
|
||||
return dto, err
|
||||
}
|
||||
|
||||
func (svc *ListService) ListUsers(ctx context.Context, opts ListUsersOption) ([]user.User, error) {
|
||||
u, err := svc.Users.List()
|
||||
return u, errors.Wrap(err, "list users from api request")
|
||||
}
|
||||
|
||||
func (svc *ListService) GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byte, error) {
|
||||
_, cert, err := svc.Tokens.DEPKeypair()
|
||||
if err != nil {
|
||||
|
||||
@@ -18,7 +18,6 @@ type HTTPHandlers struct {
|
||||
GetDEPProfileHandler http.Handler
|
||||
GetDEPDeviceDetailsHandler http.Handler
|
||||
ListAppsHandler http.Handler
|
||||
ListUsersHander http.Handler
|
||||
}
|
||||
|
||||
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
|
||||
@@ -58,12 +57,6 @@ func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptran
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
ListUsersHander: httptransport.NewServer(
|
||||
endpoints.ListUserEndpoint,
|
||||
decodeListUsersRequest,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -79,11 +72,6 @@ func decodeListDevicesRequest(ctx context.Context, r *http.Request) (interface{}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListUsersRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
req := userRequest{}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeDepAccountInfoRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -210,12 +198,3 @@ func DecodeListAppsResponse(_ context.Context, r *http.Response) (interface{}, e
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeListUsersResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp userResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, errors.Wrap(err, "decode user response")
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ const (
|
||||
type DB struct {
|
||||
*bolt.DB
|
||||
profDB profile.Store
|
||||
userDB *user.DB
|
||||
userDB user.Store
|
||||
}
|
||||
|
||||
func NewDB(
|
||||
db *bolt.DB,
|
||||
profileDB profile.Store,
|
||||
userDB *user.DB,
|
||||
userDB user.Store,
|
||||
) (*DB, error) {
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists([]byte(blueprintIndexBucket))
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
)
|
||||
|
||||
@@ -23,7 +22,7 @@ func MakeServerEndpoints(s Service) Endpoints {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler {
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) *mux.Router {
|
||||
r, options := httputil.NewRouter(logger)
|
||||
|
||||
// PUT /v1/blueprints create or replace a blueprint on the server
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
)
|
||||
|
||||
@@ -23,7 +22,7 @@ func MakeServerEndpoints(s Service) Endpoints {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler {
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) *mux.Router {
|
||||
r, options := httputil.NewRouter(logger)
|
||||
|
||||
// GET /v1/profiles get a list of profiles managed by the server
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package remove
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
)
|
||||
|
||||
@@ -21,7 +20,7 @@ func MakeServerEndpoints(s Service) Endpoints {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler {
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) *mux.Router {
|
||||
r, options := httputil.NewRouter(logger)
|
||||
|
||||
// POST /v1/devices/:udid/block force a device to unenroll next time it connects
|
||||
|
||||
69
platform/user/apply_user.go
Normal file
69
platform/user/apply_user.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (svc *UserService) ApplyUser(ctx context.Context, u User) (*User, error) {
|
||||
toSave := &u
|
||||
if u.UUID == "" { //newUser
|
||||
usr, err := NewFromRequest(u)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create user from request")
|
||||
}
|
||||
toSave = usr
|
||||
}
|
||||
err := svc.store.Save(toSave)
|
||||
return toSave, errors.Wrap(err, "apply user")
|
||||
}
|
||||
|
||||
type applyUserRequest struct {
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
type applyUserResponse struct {
|
||||
User User `json:"user"`
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r applyUserResponse) Failed() error { return r.Err }
|
||||
|
||||
func decodeApplyUserRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req applyUserRequest
|
||||
err := httputil.DecodeJSONRequest(r, &req)
|
||||
return req, err
|
||||
}
|
||||
|
||||
func decodeApplyUserResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
var resp applyUserResponse
|
||||
err := httputil.DecodeJSONResponse(r, &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func MakeApplyUserEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(applyUserRequest)
|
||||
u, err := svc.ApplyUser(ctx, req.User)
|
||||
return applyUserResponse{
|
||||
User: *u,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e Endpoints) ApplyUser(ctx context.Context, u User) (*User, error) {
|
||||
request := applyUserRequest{
|
||||
User: u,
|
||||
}
|
||||
resp, err := e.ApplyUserEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usr := resp.(applyUserResponse).User
|
||||
return &usr, resp.(applyUserResponse).Err
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package user
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/micromdm/micromdm/mdm/checkin"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,14 +52,14 @@ func NewDB(db *bolt.DB, pubsubSvc pubsub.PublishSubscriber, logger log.Logger) (
|
||||
return datastore, nil
|
||||
}
|
||||
|
||||
func (db *DB) List() ([]User, error) {
|
||||
var users []User
|
||||
func (db *DB) List() ([]user.User, error) {
|
||||
var users []user.User
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(UserBucket))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
var u User
|
||||
if err := UnmarshalUser(v, &u); err != nil {
|
||||
var u user.User
|
||||
if err := user.UnmarshalUser(v, &u); err != nil {
|
||||
return err
|
||||
}
|
||||
users = append(users, u)
|
||||
@@ -68,7 +69,7 @@ func (db *DB) List() ([]User, error) {
|
||||
return users, errors.Wrap(err, "list users")
|
||||
}
|
||||
|
||||
func (db *DB) Save(u *User) error {
|
||||
func (db *DB) Save(u *user.User) error {
|
||||
tx, err := db.DB.Begin(true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "begin transaction")
|
||||
@@ -77,7 +78,7 @@ func (db *DB) Save(u *User) error {
|
||||
if bkt == nil {
|
||||
return fmt.Errorf("bucket %q not found!", UserBucket)
|
||||
}
|
||||
userpb, err := MarshalUser(u)
|
||||
userpb, err := user.MarshalUser(u)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshalling user")
|
||||
}
|
||||
@@ -106,15 +107,15 @@ func (db *DB) Save(u *User) error {
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (db *DB) User(uuid string) (*User, error) {
|
||||
var u User
|
||||
func (db *DB) User(uuid string) (*user.User, error) {
|
||||
var u user.User
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(UserBucket))
|
||||
v := b.Get([]byte(uuid))
|
||||
if v == nil {
|
||||
return ¬Found{"User", fmt.Sprintf("uuid %s", uuid)}
|
||||
}
|
||||
return UnmarshalUser(v, &u)
|
||||
return user.UnmarshalUser(v, &u)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get user by uuid from bolt")
|
||||
@@ -122,8 +123,8 @@ func (db *DB) User(uuid string) (*User, error) {
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func (db *DB) UserByUserID(userID string) (*User, error) {
|
||||
var u User
|
||||
func (db *DB) UserByUserID(userID string) (*user.User, error) {
|
||||
var u user.User
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(UserBucket))
|
||||
ib := tx.Bucket([]byte(userIndexBucket))
|
||||
@@ -135,7 +136,7 @@ func (db *DB) UserByUserID(userID string) (*User, error) {
|
||||
if idx == nil {
|
||||
return ¬Found{"User", fmt.Sprintf("uuid %s", string(idx))}
|
||||
}
|
||||
return UnmarshalUser(v, &u)
|
||||
return user.UnmarshalUser(v, &u)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get user by user id from bolt")
|
||||
@@ -143,14 +144,14 @@ func (db *DB) UserByUserID(userID string) (*User, error) {
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func (db *DB) DeviceUsers(udid string) ([]User, error) {
|
||||
var users []User
|
||||
func (db *DB) DeviceUsers(udid string) ([]user.User, error) {
|
||||
var users []user.User
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(UserBucket))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
var u User
|
||||
if err := UnmarshalUser(v, &u); err != nil {
|
||||
var u user.User
|
||||
if err := user.UnmarshalUser(v, &u); err != nil {
|
||||
return errors.Wrap(err, "unmarshal user for DeviceUsers")
|
||||
}
|
||||
if u.UDID == udid {
|
||||
@@ -170,8 +171,8 @@ func (db *DB) DeleteDeviceUsers(udid string) error {
|
||||
b := tx.Bucket([]byte(UserBucket))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
var u User
|
||||
if err := UnmarshalUser(v, &u); err != nil {
|
||||
var u user.User
|
||||
if err := user.UnmarshalUser(v, &u); err != nil {
|
||||
return errors.Wrap(err, "unmarshal user for DeviceUsers")
|
||||
}
|
||||
if u.UDID != udid {
|
||||
@@ -195,6 +196,10 @@ func (e *notFound) Error() string {
|
||||
return fmt.Sprintf("not found: %s %s", e.ResourceType, e.Message)
|
||||
}
|
||||
|
||||
func (e *notFound) NotFound() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
|
||||
tokenUpdateEvents, err := pubsubSvc.Subscribe(context.TODO(), "users", checkin.TokenUpdateTopic)
|
||||
if err != nil {
|
||||
@@ -213,7 +218,7 @@ func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
|
||||
if event.Command.UserID == "" {
|
||||
break // only interested in user commands
|
||||
}
|
||||
newUser := new(User)
|
||||
newUser := new(user.User)
|
||||
byGUID, err := db.UserByUserID(event.Command.UserID)
|
||||
if err != nil && !isNotFound(err) {
|
||||
level.Info(db.logger).Log("err", err, "msg", "get user from DB")
|
||||
44
platform/user/client.go
Normal file
44
platform/user/client.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
)
|
||||
|
||||
func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransport.ClientOption) (Service, error) {
|
||||
u, err := url.Parse(instance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var applyUserEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyUserEndpoint = httptransport.NewClient(
|
||||
"PUT",
|
||||
httputil.CopyURL(u, "/v1/users"),
|
||||
httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest),
|
||||
decodeApplyUserResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var listUsersEndpoint endpoint.Endpoint
|
||||
{
|
||||
listUsersEndpoint = httptransport.NewClient(
|
||||
"GET",
|
||||
httputil.CopyURL(u, "/v1/users"),
|
||||
httputil.EncodeRequestWithToken(token, httptransport.EncodeJSONRequest),
|
||||
decodeListUsersResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
ApplyUserEndpoint: applyUserEndpoint,
|
||||
ListUsersEndpoint: listUsersEndpoint,
|
||||
}, nil
|
||||
}
|
||||
59
platform/user/list_user.go
Normal file
59
platform/user/list_user.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (svc *UserService) ListUsers(ctx context.Context, opts ListUsersOption) ([]User, error) {
|
||||
u, err := svc.store.List()
|
||||
return u, errors.Wrap(err, "list users from api request")
|
||||
}
|
||||
|
||||
type getUsersRequest struct{ Opts ListUsersOption }
|
||||
type getUsersResponse struct {
|
||||
Users []User `json:"users"`
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r getUsersResponse) Failed() error { return r.Err }
|
||||
|
||||
func decodeListUsersRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var opts ListUsersOption
|
||||
if err := json.NewDecoder(r.Body).Decode(&opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := getUsersRequest{Opts: opts}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeListUsersResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
var resp getUsersResponse
|
||||
err := httputil.DecodeJSONResponse(r, &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func MakeListUsersEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(getUsersRequest)
|
||||
users, err := svc.ListUsers(ctx, req.Opts)
|
||||
return getUsersResponse{
|
||||
Users: users,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e Endpoints) ListUsers(ctx context.Context, opts ListUsersOption) ([]User, error) {
|
||||
request := getUsersRequest{opts}
|
||||
response, err := e.ListUsersEndpoint(ctx, request.Opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.(getUsersResponse).Users, response.(getUsersResponse).Err
|
||||
}
|
||||
45
platform/user/server.go
Normal file
45
platform/user/server.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/micromdm/micromdm/pkg/httputil"
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
ApplyUserEndpoint endpoint.Endpoint
|
||||
ListUsersEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
func MakeServerEndpoints(s Service) Endpoints {
|
||||
return Endpoints{
|
||||
ApplyUserEndpoint: MakeApplyUserEndpoint(s),
|
||||
ListUsersEndpoint: MakeListUsersEndpoint(s),
|
||||
}
|
||||
}
|
||||
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) *mux.Router {
|
||||
r, options := httputil.NewRouter(logger)
|
||||
|
||||
// PUT /v1/users create or replace an user
|
||||
// GET /v1/users get a list of users managed by the server
|
||||
|
||||
r.Methods("PUT").Path("/v1/users").Handler(httptransport.NewServer(
|
||||
e.ApplyUserEndpoint,
|
||||
decodeApplyUserRequest,
|
||||
httputil.EncodeJSONResponse,
|
||||
options...,
|
||||
))
|
||||
|
||||
r.Methods("GET").Path("/v1/users").Handler(httptransport.NewServer(
|
||||
e.ListUsersEndpoint,
|
||||
decodeListUsersRequest,
|
||||
httputil.EncodeJSONResponse,
|
||||
options...,
|
||||
))
|
||||
|
||||
return r
|
||||
}
|
||||
32
platform/user/service.go
Normal file
32
platform/user/service.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ListUsersOption struct {
|
||||
Page int `json:"page"`
|
||||
PerPage int `json:"per_page"`
|
||||
|
||||
FilterUserID []string `json:"filter_user_id"`
|
||||
FilterUDID []string `json:"filter_udid"`
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
ApplyUser(ctx context.Context, u User) (*User, error)
|
||||
ListUsers(ctx context.Context, opt ListUsersOption) ([]User, error)
|
||||
}
|
||||
|
||||
type Store interface {
|
||||
User(string) (*User, error)
|
||||
Save(*User) error
|
||||
List() ([]User, error)
|
||||
}
|
||||
|
||||
type UserService struct {
|
||||
store Store
|
||||
}
|
||||
|
||||
func New(store Store) *UserService {
|
||||
return &UserService{store: store}
|
||||
}
|
||||
Reference in New Issue
Block a user