//PutRepositoryV1Handler will create or update the repository, it's first step of Docker push. //TODO: @1 When someone create or update the repository, it will be locked to forbidden others action include pull action. //TODO: @2 Add a config option for allow/forbidden Docker client pull action when a repository is locked. //TODO: @3 Intergated with [Crew](https://github.com/containerops/crew). //TODO: @4 Token will be store in Redis, and link the push action with username@repository. func PutRepositoryV1Handler(ctx *macaron.Context) (int, []byte) { var username, body string //var passwd string var err error if username, _, err = utils.DecodeBasicAuth(ctx.Req.Header.Get("Authorization")); err != nil { log.Errorf("[%s] decode Authorization error: %s", ctx.Req.RequestURI, err.Error()) result, _ := json.Marshal(map[string]string{"Error": "Decode Authorization Error"}) return http.StatusUnauthorized, result } //When integrated with crew, like this: //@1: username, passwd, _ := utils.DecodeBasicAuth(ctx.Req.Header.Get("Authorization")) //@2: username, passwd authorizated in Crew. namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") //When integrated the Crew, should be check the privilage. if username != namespace { } //In Docker Registry V1, the repository json data in the body of `PUT /v1/:namespace/:repository` if body, err = ctx.Req.Body().String(); err != nil { log.Errorf("[%s] get repository json from http body error: %s", ctx.Req.RequestURI, err.Error()) result, _ := json.Marshal(map[string]string{"Error": "Get Repository JSON Error"}) return http.StatusBadRequest, result } //Create or update the repository. r := new(models.DockerV1) if e := r.Put(namespace, repository, body, ctx.Req.Header.Get("User-Agent")); e != nil { log.Errorf("[%s] put repository error: %s", ctx.Req.RequestURI, e.Error()) result, _ := json.Marshal(map[string]string{"Error": "PUT Repository Error"}) return http.StatusBadRequest, result } //If the Docker client use "X-Docker-Token", will return a randon token value. if ctx.Req.Header.Get("X-Docker-Token") == "true" { token := fmt.Sprintf("Token signature=%v,repository=\"%v/%v\",access=%v", utils.MD5(username), namespace, repository, "write") ctx.Resp.Header().Set("X-Docker-Token", token) ctx.Resp.Header().Set("WWW-Authenticate", token) } //TODO: When deploy multi instances of dockyard, the endpoints will schedule comply all instances stauts and arithmetic. ctx.Resp.Header().Set("X-Docker-Endpoints", setting.Domains) result, _ := json.Marshal(map[string]string{}) return http.StatusOK, result }