mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.9 KiB
150 lines
3.9 KiB
// package admin provides an implementation of the API described in auth/schema/adminschema. |
|
package admin |
|
|
|
import ( |
|
"net/http" |
|
|
|
"github.com/coreos/go-oidc/oidc" |
|
"github.com/go-gorp/gorp" |
|
|
|
"github.com/coreos/dex/client" |
|
"github.com/coreos/dex/db" |
|
"github.com/coreos/dex/schema/adminschema" |
|
"github.com/coreos/dex/user" |
|
"github.com/coreos/dex/user/manager" |
|
) |
|
|
|
// AdminAPI provides the logic necessary to implement the Admin API. |
|
type AdminAPI struct { |
|
userManager *manager.UserManager |
|
userRepo user.UserRepo |
|
passwordInfoRepo user.PasswordInfoRepo |
|
clientIdentityRepo client.ClientIdentityRepo |
|
localConnectorID string |
|
} |
|
|
|
// TODO(ericchiang): Swap the DbMap for a storage interface. See #278 |
|
|
|
func NewAdminAPI(dbMap *gorp.DbMap, userManager *manager.UserManager, localConnectorID string) *AdminAPI { |
|
if localConnectorID == "" { |
|
panic("must specify non-blank localConnectorID") |
|
} |
|
return &AdminAPI{ |
|
userManager: userManager, |
|
userRepo: db.NewUserRepo(dbMap), |
|
passwordInfoRepo: db.NewPasswordInfoRepo(dbMap), |
|
clientIdentityRepo: db.NewClientIdentityRepo(dbMap), |
|
localConnectorID: localConnectorID, |
|
} |
|
} |
|
|
|
// Error is the error type returned by AdminAPI methods. |
|
type Error struct { |
|
Type string |
|
|
|
// The HTTP Code to return for this type of error. |
|
Code int |
|
|
|
Desc string |
|
|
|
// The underlying error - not to be consumed by external users. |
|
Internal error |
|
} |
|
|
|
func (e Error) Error() string { |
|
return e.Type |
|
} |
|
|
|
func errorMaker(typ string, desc string, code int) func(internal error) Error { |
|
return func(internal error) Error { |
|
return Error{ |
|
Type: typ, |
|
Code: code, |
|
Desc: desc, |
|
Internal: internal, |
|
} |
|
} |
|
} |
|
|
|
var ( |
|
errorMap = map[error]func(error) Error{ |
|
user.ErrorNotFound: errorMaker("resource_not_found", "Resource could not be found.", http.StatusNotFound), |
|
user.ErrorDuplicateEmail: errorMaker("bad_request", "Email already in use.", http.StatusBadRequest), |
|
user.ErrorInvalidEmail: errorMaker("bad_request", "invalid email.", http.StatusBadRequest), |
|
} |
|
) |
|
|
|
func (a *AdminAPI) GetAdmin(id string) (adminschema.Admin, error) { |
|
usr, err := a.userRepo.Get(nil, id) |
|
|
|
if err != nil { |
|
return adminschema.Admin{}, mapError(err) |
|
} |
|
|
|
pwi, err := a.passwordInfoRepo.Get(nil, id) |
|
if err != nil { |
|
return adminschema.Admin{}, mapError(err) |
|
} |
|
|
|
return adminschema.Admin{ |
|
Id: id, |
|
Email: usr.Email, |
|
Password: string(pwi.Password), |
|
}, nil |
|
} |
|
|
|
func (a *AdminAPI) CreateAdmin(admn adminschema.Admin) (string, error) { |
|
userID, err := a.userManager.CreateUser(user.User{ |
|
Email: admn.Email, |
|
Admin: true}, user.Password(admn.Password), a.localConnectorID) |
|
if err != nil { |
|
return "", mapError(err) |
|
} |
|
return userID, nil |
|
} |
|
|
|
func (a *AdminAPI) GetState() (adminschema.State, error) { |
|
state := adminschema.State{} |
|
|
|
admins, err := a.userRepo.GetAdminCount(nil) |
|
if err != nil { |
|
return adminschema.State{}, err |
|
} |
|
|
|
state.AdminUserCreated = admins > 0 |
|
|
|
return state, nil |
|
} |
|
|
|
type ClientRegistrationRequest struct { |
|
IsAdmin bool `json:"isAdmin"` |
|
Client oidc.ClientMetadata `json:"client"` |
|
} |
|
|
|
func (a *AdminAPI) CreateClient(req ClientRegistrationRequest) (oidc.ClientRegistrationResponse, error) { |
|
if err := req.Client.Valid(); err != nil { |
|
return oidc.ClientRegistrationResponse{}, mapError(err) |
|
} |
|
// metadata is guarenteed to have at least one redirect_uri by earlier validation. |
|
id, err := oidc.GenClientID(req.Client.RedirectURIs[0].Host) |
|
if err != nil { |
|
return oidc.ClientRegistrationResponse{}, mapError(err) |
|
} |
|
c, err := a.clientIdentityRepo.New(id, req.Client, req.IsAdmin) |
|
if err != nil { |
|
return oidc.ClientRegistrationResponse{}, mapError(err) |
|
} |
|
return oidc.ClientRegistrationResponse{ClientID: c.ID, ClientSecret: c.Secret, ClientMetadata: req.Client}, nil |
|
} |
|
|
|
func mapError(e error) error { |
|
if mapped, ok := errorMap[e]; ok { |
|
return mapped(e) |
|
} |
|
return Error{ |
|
Code: http.StatusInternalServerError, |
|
Type: "server_error", |
|
Desc: "", |
|
Internal: e, |
|
} |
|
}
|
|
|