Beispiel #1
0
// Delete accepts a request to delete a worker
// from the pool.
//
//     DELETE /sudo/api/workers/:id
//
func DelWorker(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	pool := pool.FromContext(ctx)
	uuid := c.URLParams["id"]

	server, err := datastore.GetServer(ctx, uuid)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	err = datastore.DelServer(ctx, server)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	for _, worker := range pool.List() {
		if worker.(*docker.Docker).UUID == uuid {
			pool.Deallocate(worker)
			w.WriteHeader(http.StatusNoContent)
			return
		}
	}
	w.WriteHeader(http.StatusNotFound)
}
Beispiel #2
0
// CreatePerson accepts a request to add a new person.
//
//     POST /api/people
//
func CreatePerson(c web.C, w http.ResponseWriter, r *http.Request) {
	var (
		ctx = context.FromC(c)
	)

	// Unmarshal the person from the payload
	defer r.Body.Close()
	in := struct {
		Name string `json:"name"`
	}{}
	if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Validate input
	if len(in.Name) < 1 {
		http.Error(w, "no name given", http.StatusBadRequest)
		return
	}

	// Create our 'normal' model.
	person := &model.Person{Name: in.Name}
	err := datastore.CreatePerson(ctx, person)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(person)
}
Beispiel #3
0
// PostWorker accepts a request to allocate a new
// worker to the pool.
//
//     POST /api/workers
//
func PostWorker(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	pool := pool.FromContext(ctx)
	node := r.FormValue("address")
	pool.Allocate(docker.NewHost(node))
	w.WriteHeader(http.StatusOK)
}
Beispiel #4
0
// GetCC accepts a request to retrieve the latest build
// status for the given repository from the datastore and
// in CCTray XML format.
//
//     GET /api/badge/:host/:owner/:name/cc.xml
//
func GetCC(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		host  = c.URLParams["host"]
		owner = c.URLParams["owner"]
		name  = c.URLParams["name"]
	)

	w.Header().Set("Content-Type", "application/xml")

	repo, err := datastore.GetRepoName(ctx, host, owner, name)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	commits, err := datastore.GetCommitList(ctx, repo, 1, 0)
	if err != nil || len(commits) == 0 {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	var link = httputil.GetURL(r) + "/" + repo.Host + "/" + repo.Owner + "/" + repo.Name
	var cc = model.NewCC(repo, commits[0], link)
	xml.NewEncoder(w).Encode(cc)
}
Beispiel #5
0
// PutRegion accepts a request to retrieve information about a particular region.
//
//     PUT /api/regions/:region
//
func PutRegion(c web.C, w http.ResponseWriter, r *http.Request) {
	var (
		ctx    = context.FromC(c)
		idStr  = c.URLParams["region"]
		region model.Region
	)

	id, err := strconv.ParseInt(idStr, 10, 64)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if !regionFromRequest(c, w, r, &region) {
		return
	}
	region.ID = id

	err = datastore.UpdateRegion(ctx, &region)
	if err != nil {
		log.FromContext(ctx).WithField("err", err).Error("Error updating region")
		w.WriteHeader(http.StatusNotFound)
		return
	}

	json.NewEncoder(w).Encode(&region)
}
Beispiel #6
0
// SetRepo is a middleware function that retrieves
// the repository and stores in the context.
func SetRepo(c *web.C, h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		var (
			ctx   = context.FromC(*c)
			host  = c.URLParams["host"]
			owner = c.URLParams["owner"]
			name  = c.URLParams["name"]
			user  = ToUser(c)
		)

		repo, err := datastore.GetRepoName(ctx, host, owner, name)
		switch {
		case err != nil && user == nil:
			w.WriteHeader(http.StatusUnauthorized)
			return
		case err != nil && user != nil:
			w.WriteHeader(http.StatusNotFound)
			return
		}
		role, _ := datastore.GetPerm(ctx, user, repo)
		RepoToC(c, repo)
		RoleToC(c, role)
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(fn)
}
Beispiel #7
0
// GetBuildPage accepts a request to retrieve the build
// output page for the package version, channel and SDK
// from the datastore in JSON format.
//
// If the SDK is not provided, the system will lookup
// the latest SDK version for this package.
//
//     GET /:name/:number/:channel/:sdk
//
func GetBuildPage(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	name := c.URLParams["name"]
	number := c.URLParams["number"]
	channel := c.URLParams["channel"]
	sdk := c.URLParams["sdk"]

	// If no SDK is provided we should use the most recent
	// SDK number associated with the Package version.
	var build *resource.Build
	var err error
	if len(sdk) == 0 {
		build, err = datastore.GetBuildLatest(ctx, name, number, channel)
	} else {
		build, err = datastore.GetBuild(ctx, name, number, channel, sdk)
	}

	// If the error is not nil then we can
	// display some sort of NotFound page.
	if err != nil {
		http.Error(w, "Not Found", http.StatusNotFound)
		return
	}

	BuildTempl.Execute(w, struct {
		Build *resource.Build
		Error error
	}{build, err})
}
Beispiel #8
0
// PostUserSync accepts a request to post user sync
//
//     POST /api/user/sync
//
func PostUserSync(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var user = ToUser(c)
	if user == nil {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	var remote = remote.Lookup(user.Remote)
	if remote == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if user.Syncing {
		w.WriteHeader(http.StatusConflict)
		return
	}

	user.Syncing = true
	if err := datastore.PutUser(ctx, user); err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	go sync.SyncUser(ctx, user, remote)
	w.WriteHeader(http.StatusNoContent)
	return
}
Beispiel #9
0
// PutUser accepts a request to update the currently
// authenticated User profile.
//
//     PUT /api/user
//
func PutUser(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var user = ToUser(c)
	if user == nil {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	// unmarshal the repository from the payload
	defer r.Body.Close()
	in := model.User{}
	if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// update the user email
	if len(in.Email) != 0 {
		user.SetEmail(in.Email)
	}
	// update the user full name
	if len(in.Name) != 0 {
		user.Name = in.Name
	}

	// update the database
	if err := datastore.PutUser(ctx, user); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	json.NewEncoder(w).Encode(user)
}
Beispiel #10
0
// PostWorker accepts a request to allocate a new
// worker to the pool.
//
//     POST /sudo/api/workers
//
func PostWorker(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	pool := pool.FromContext(ctx)
	server := resource.Server{}

	// read the worker data from the body
	defer r.Body.Close()
	if err := json.NewDecoder(r.Body).Decode(&server); err != nil {
		println(err.Error())
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// add the worker to the database
	err := datastore.PutServer(ctx, &server)
	if err != nil {
		println(err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// create a new worker from the Docker client
	client, err := docker.NewCert(server.Host, []byte(server.Cert), []byte(server.Key))
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// append user-friendly data to the host
	client.Host = client.Host

	pool.Allocate(client)
	w.WriteHeader(http.StatusOK)
}
Beispiel #11
0
// PostHook accepts a post-commit hook and parses the payload
// in order to trigger a build. The payload is specified to the
// remote system (ie GitHub) and will therefore get parsed by
// the appropriate remote plugin.
//
//     POST /api/repos/{host}/{owner}/{name}/branches/{branch}/commits/{commit}
//
func PostCommit(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		branch = c.URLParams["branch"]
		hash   = c.URLParams["commit"]
		host   = c.URLParams["host"]
		repo   = ToRepo(c)
		remote = remote.Lookup(host)
	)

	commit, err := datastore.GetCommitSha(ctx, repo, branch, hash)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	if commit.Status == model.StatusStarted ||
		commit.Status == model.StatusEnqueue {
		w.WriteHeader(http.StatusConflict)
		return
	}

	commit.Status = model.StatusEnqueue
	commit.Started = 0
	commit.Finished = 0
	commit.Duration = 0
	if err := datastore.PutCommit(ctx, commit); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	owner, err := datastore.GetUser(ctx, repo.UserID)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Request a new token and update
	user_token, err := remote.GetToken(owner)
	if user_token != nil {
		owner.Access = user_token.AccessToken
		owner.Secret = user_token.RefreshToken
		owner.TokenExpiry = user_token.Expiry
		datastore.PutUser(ctx, owner)
	} else if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// drop the items on the queue
	go worker.Do(ctx, &worker.Work{
		User:   owner,
		Repo:   repo,
		Commit: commit,
		Host:   httputil.GetURL(r),
	})

	w.WriteHeader(http.StatusOK)
}
Beispiel #12
0
// WsUser will upgrade the connection to a Websocket and will stream
// all events to the browser pertinent to the authenticated user. If the user
// is not authenticated, only public events are streamed.
func WsUser(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var user = ToUser(c)

	// upgrade the websocket
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// register a channel for global events
	channel := pubsub.Register(ctx, "_global")
	sub := channel.Subscribe()

	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		sub.Close()
		ws.Close()
	}()

	go func() {
		for {
			select {
			case msg := <-sub.Read():
				work, ok := msg.(*worker.Work)
				if !ok {
					break
				}

				// user must have read access to the repository
				// in order to pass this message along
				if role, err := datastore.GetPerm(ctx, user, work.Repo); err != nil || role.Read == false {
					break
				}

				ws.SetWriteDeadline(time.Now().Add(writeWait))
				err := ws.WriteJSON(work)
				if err != nil {
					ws.Close()
					return
				}
			case <-sub.CloseNotify():
				ws.Close()
				return
			case <-ticker.C:
				ws.SetWriteDeadline(time.Now().Add(writeWait))
				err := ws.WriteMessage(websocket.PingMessage, []byte{})
				if err != nil {
					ws.Close()
					return
				}
			}
		}
	}()

	readWebsocket(ws)
}
Beispiel #13
0
// PostUser accepts a request to create a new user in the
// system. The created user account is returned in JSON
// format if successful.
//
//     POST /api/users/:host/:login
//
func PostUser(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		host  = c.URLParams["host"]
		login = c.URLParams["login"]
	)
	var remote = remote.Lookup(host)
	if remote == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// not sure I love this, but POST now flexibly accepts the oauth_token for
	// GitHub as either application/x-www-form-urlencoded OR as applcation/json
	// with this format:
	//    { "oauth_token": "...." }
	var oauthToken string
	switch cnttype := r.Header.Get("Content-Type"); cnttype {
	case "application/json":
		var out interface{}
		err := json.NewDecoder(r.Body).Decode(&out)
		if err == nil {
			if val, ok := out.(map[string]interface{})["oauth_token"]; ok {
				oauthToken = val.(string)
			}
		}
	case "application/x-www-form-urlencoded":
		oauthToken = r.PostForm.Get("oauth_token")
	default:
		// we don't recognize the content-type, but it isn't worth it
		// to error here
		log.Printf("PostUser(%s) Unknown 'Content-Type': %s)", r.URL, cnttype)
	}
	account := model.NewUser(host, login, "", oauthToken)

	if err := datastore.PostUser(ctx, account); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// borrowed this concept from login.go. upon first creation we
	// may trying syncing the user's repositories.
	account.Syncing = account.IsStale()
	if err := datastore.PutUser(ctx, account); err != nil {
		log.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if account.Syncing {
		log.Println("sync user account.", account.Login)

		// sync inside a goroutine
		go sync.SyncUser(ctx, account, remote)
	}

	json.NewEncoder(w).Encode(account)
}
Beispiel #14
0
func main() {
	extdirect.Provider.RegisterAction(reflect.TypeOf(Db{}))
	goji.Get(extdirect.Provider.URL, extdirect.API(extdirect.Provider))
	goji.Post(extdirect.Provider.URL, func(c web.C, w http.ResponseWriter, r *http.Request) {
		extdirect.ActionsHandlerCtx(extdirect.Provider)(gcontext.FromC(c), w, r)
	})
	goji.Use(gojistatic.Static("public", gojistatic.StaticOptions{SkipLogging: true}))
	goji.Serve()
}
Beispiel #15
0
// GetFeed accepts a request to retrieve a feed
// of the latest builds in JSON format.
//
//     GET /api/feed
//
func GetFeed(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	pkg, err := datastore.GetFeed(ctx)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(pkg)
}
Beispiel #16
0
// GetUserList accepts a request to retrieve all users
// from the datastore and return encoded in JSON format.
//
//     GET /api/users
//
func GetUserList(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)

	users, err := datastore.GetUserList(ctx)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(users)
}
Beispiel #17
0
// GetChannel accepts a request to retrieve the latest
// SDK version and revision for the specified channel.
//
//     GET /api/channel/:name
//
func GetChannel(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	name := c.URLParams["channel"]
	channel, err := datastore.GetChannel(ctx, name)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(channel)
}
Beispiel #18
0
// SetUser is a middleware function that retrieves
// the currently authenticated user from the request
// and stores in the context.
func SetUser(c *web.C, h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		var ctx = context.FromC(*c)
		var user = session.GetUser(ctx, r)
		if user != nil && user.ID != 0 {
			UserToC(c, user)
		}
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(fn)
}
Beispiel #19
0
// GetCommitList accepts a request to retrieve a list
// of recent commits by Repo, and retur in JSON format.
//
//     GET /api/repos/:host/:owner/:name/commits
//
func GetCommitList(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var repo = ToRepo(c)

	commits, err := datastore.GetCommitList(ctx, repo)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	json.NewEncoder(w).Encode(commits)
}
Beispiel #20
0
// GetBuildLatest accepts a request to retrieve the build
// details for the package version, channel and latest SDK
// from the datastore in JSON format.
//
//     GET /api/packages/:name/:number/channel/:channel
//
func GetBuildLatest(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	name := c.URLParams["name"]
	number := c.URLParams["number"]
	channel := c.URLParams["channel"]

	build, err := datastore.GetBuildLatest(ctx, name, number, channel)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(build)
}
Beispiel #21
0
// RecoverMiddleware helps the server recover from panics.  It ensures that
// no request can fully bring down the horizon server, and it also logs the
// panics to the logging subsystem.
func RecoverMiddleware(c *web.C, h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		ctx := gctx.FromC(*c)

		defer func() {
			if err := recover(); err != nil {
				stack := make([]byte, 4096) // 4k of stack should be sufficient to see the source
				n := runtime.Stack(stack, false)

				log.
					WithField(ctx, "stacktrace", string(stack[:n])).
					Errorf("panic: %+v", err)

				//TODO: include stack trace if in debug mode
				problem.Render(gctx.FromC(*c), w, problem.ServerError)
			}
		}()

		h.ServeHTTP(w, r)
	}

	return http.HandlerFunc(fn)
}
Beispiel #22
0
// PutRepo accapets a request to update the named repository
// in the datastore. It expects a JSON input and returns the
// updated repository in JSON format if successful.
//
//     PUT /api/repos/:host/:owner/:name
//
func PutRepo(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var repo = ToRepo(c)
	var user = ToUser(c)

	// unmarshal the repository from the payload
	defer r.Body.Close()
	in := struct {
		PostCommit  *bool   `json:"post_commits"`
		PullRequest *bool   `json:"pull_requests"`
		Privileged  *bool   `json:"privileged"`
		Params      *string `json:"params"`
		Timeout     *int64  `json:"timeout"`
		PublicKey   *string `json:"public_key"`
		PrivateKey  *string `json:"private_key"`
	}{}
	if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if in.Params != nil {
		repo.Params = *in.Params
		if _, err := repo.ParamMap(); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}
	if in.PostCommit != nil {
		repo.PostCommit = *in.PostCommit
	}
	if in.PullRequest != nil {
		repo.PullRequest = *in.PullRequest
	}
	if in.Privileged != nil && user.Admin {
		repo.Privileged = *in.Privileged
	}
	if in.Timeout != nil && user.Admin {
		repo.Timeout = *in.Timeout
	}
	if in.PrivateKey != nil && in.PublicKey != nil {
		repo.PublicKey = *in.PublicKey
		repo.PrivateKey = *in.PrivateKey
	}
	if err := datastore.PutRepo(ctx, repo); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	json.NewEncoder(w).Encode(repo)
}
Beispiel #23
0
// PostUser accepts a request to create a new user in the
// system. The created user account is returned in JSON
// format if successful.
//
//     POST /api/users/:host/:login
//
func PostUser(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		host  = c.URLParams["host"]
		login = c.URLParams["login"]
	)

	account := model.NewUser(host, login, "")
	if err := datastore.PostUser(ctx, account); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	json.NewEncoder(w).Encode(account)
}
Beispiel #24
0
// GetUserFeed accepts a request to get the user's latest
// build feed, across all repositories, from the datastore.
// The results are encoded and returned in JSON format.
//
//     GET /api/user/feed
//
func GetUserFeed(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var user = ToUser(c)
	if user == nil {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	repos, err := datastore.GetCommitListUser(ctx, user)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(&repos)
}
Beispiel #25
0
// GetBadge accepts a request to retrieve the named
// repo and branhes latest build details from the datastore
// and return an SVG badges representing the build results.
//
//     GET /api/badge/:host/:owner/:name/status.svg
//
func GetBadge(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		host   = c.URLParams["host"]
		owner  = c.URLParams["owner"]
		name   = c.URLParams["name"]
		branch = r.FormValue("branch")
		style  = r.FormValue("style")
	)

	// an SVG response is always served, even when error, so
	// we can go ahead and set the content type appropriately.
	w.Header().Set("Content-Type", "image/svg+xml")

	badge, ok := badgeStyles[style]
	if !ok {
		badge = defaultBadge
	}

	repo, err := datastore.GetRepoName(ctx, host, owner, name)
	if err != nil {
		w.Write(badge.none)
		return
	}
	if len(branch) == 0 {
		branch = model.DefaultBranch
	}
	commit, _ := datastore.GetCommitLast(ctx, repo, branch)

	// if no commit was found then display
	// the 'none' badge, instead of throwing
	// an error response
	if commit == nil {
		w.Write(badge.none)
		return
	}

	switch commit.Status {
	case model.StatusSuccess:
		w.Write(badge.success)
	case model.StatusFailure:
		w.Write(badge.failure)
	case model.StatusError:
		w.Write(badge.err)
	case model.StatusEnqueue, model.StatusStarted:
		w.Write(badge.started)
	default:
		w.Write(badge.none)
	}
}
Beispiel #26
0
// Delete accepts a request to delete a worker
// from the pool.
//
//     DELETE /api/workers
//
func DelWorker(c web.C, w http.ResponseWriter, r *http.Request) {
	ctx := context.FromC(c)
	pool := pool.FromContext(ctx)
	uuid := r.FormValue("id")

	for _, worker := range pool.List() {
		if worker.(*docker.Docker).UUID != uuid {
			pool.Deallocate(worker)
			w.WriteHeader(http.StatusNoContent)
			return
		}
	}
	w.WriteHeader(http.StatusNotFound)
}
Beispiel #27
0
// PostRepo accapets a request to activate the named repository
// in the datastore. It returns a 201 status created if successful
//
//     POST /api/repos/:host/:owner/:name
//
func PostRepo(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var repo = ToRepo(c)
	var user = ToUser(c)

	// update the repo active flag and fields
	repo.Active = true
	repo.PullRequest = true
	repo.PostCommit = true
	repo.UserID = user.ID
	repo.Timeout = 3600 // default to 1 hour

	// generate a secret key for post-commit hooks
	if len(repo.Token) == 0 {
		repo.Token = model.GenerateToken()
	}

	// generates the rsa key
	if len(repo.PublicKey) == 0 || len(repo.PrivateKey) == 0 {
		key, err := sshutil.GeneratePrivateKey()
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		repo.PublicKey = sshutil.MarshalPublicKey(&key.PublicKey)
		repo.PrivateKey = sshutil.MarshalPrivateKey(key)
	}

	var remote = remote.Lookup(repo.Host)
	if remote == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// setup the post-commit hook with the remote system and
	// if necessary, register the public key
	var hook = fmt.Sprintf("%s/api/hook/%s/%s", httputil.GetURL(r), repo.Remote, repo.Token)
	if err := remote.Activate(user, repo, hook); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	if err := datastore.PutRepo(ctx, repo); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(repo)
}
Beispiel #28
0
// GetUser accepts a request to retrieve a user by hostname
// and login from the datastore and return encoded in JSON
// format.
//
//     GET /api/users/:host/:login
//
func GetUser(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		user  = ToUser(c)
		host  = c.URLParams["host"]
		login = c.URLParams["login"]
	)

	user, err := datastore.GetUserLogin(ctx, host, login)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}
	json.NewEncoder(w).Encode(user)
}
Beispiel #29
0
// DelRepo accepts a request to inactivate the named
// repository. This will disable all builds in the system
// for this repository.
//
//     DEL /api/repos/:host/:owner/:name
//
func DelRepo(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var repo = ToRepo(c)

	// disable everything
	repo.Active = false
	repo.PullRequest = false
	repo.PostCommit = false

	if err := datastore.PutRepo(ctx, repo); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
Beispiel #30
0
// GetCommit accepts a request to retrieve a commit
// from the datastore for the given repository, branch and
// commit hash.
//
//     GET /api/repos/:host/:owner/:name/branches/:branch/commits/:commit
//
func GetCommit(c web.C, w http.ResponseWriter, r *http.Request) {
	var ctx = context.FromC(c)
	var (
		branch = c.URLParams["branch"]
		hash   = c.URLParams["commit"]
		repo   = ToRepo(c)
	)

	commit, err := datastore.GetCommitSha(ctx, repo, branch, hash)
	if err != nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	json.NewEncoder(w).Encode(commit)
}