コード例 #1
0
ファイル: user.go プロジェクト: robxu9/kahinah
func UserLoginHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	if !cas.IsAuthenticated(r) {
		// save the referrer
		sessionmw.Set(ctx, CASReferrer, r.Referer())

		// shut off rendering
		dataRenderer := data.FromContext(ctx)
		dataRenderer.Type = data.DataNoRender

		// and redirect
		cas.RedirectToLogin(rw, r)
	} else {
		// get the referrer
		referrer, has := sessionmw.Get(ctx, CASReferrer)
		sessionmw.Delete(ctx, CASReferrer)

		// shut off rendering
		dataRenderer := data.FromContext(ctx)
		dataRenderer.Type = data.DataNoRender

		// and redirect
		if !has {
			http.Redirect(rw, r, render.ConvertURL("/"), http.StatusTemporaryRedirect)
		} else {
			http.Redirect(rw, r, referrer.(string), http.StatusTemporaryRedirect)
		}
	}
}
コード例 #2
0
ファイル: main.go プロジェクト: robxu9/kahinah
// MainHandler shows the main page.
func MainHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)

	stat, err := os.Stat("news.md")
	var time time.Time
	if err == nil {
		time = stat.ModTime()
	}

	bte, err := ioutil.ReadFile("news.md")
	markdown := []byte("_Couldn't retrieve the latest news._")
	if err == nil {
		markdown = bte
	}

	output := blackfriday.MarkdownCommon(markdown)

	dataRenderer.Data = map[string]interface{}{
		"Title": "Main",
		"News":  template.HTML(bluemonday.UGCPolicy().SanitizeBytes(output)),
		"Time":  time,
		"Nav":   0,
	}
	dataRenderer.Template = "index"
}
コード例 #3
0
ファイル: activity.go プロジェクト: robxu9/kahinah
func ActivityHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)

	// we more or less have Vue.js show recent activity, so just render the template
	dataRenderer.Data = map[string]interface{}{
		"Title": "Recent Activity",
		"Nav":   1,
	}
	dataRenderer.Template = "i/activity"
}
コード例 #4
0
ファイル: user.go プロジェクト: robxu9/kahinah
func UserLogoutHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	// shut off rendering
	dataRenderer := data.FromContext(ctx)
	dataRenderer.Type = data.DataNoRender

	// Destroy the session
	sessionmw.Destroy(ctx, rw)

	// CAS logouts are always one-way.
	cas.RedirectToLogout(rw, r)
}
コード例 #5
0
ファイル: activity.go プロジェクト: robxu9/kahinah
func ActivityJSONHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)

	page := int(to.Int64(r.FormValue("page")))
	if page <= 0 {
		page = 1
	}

	limit := int(to.Int64(r.FormValue("limit")))
	if limit <= 0 {
		limit = 50
	}

	var cnt int
	if err := models.DB.Model(&models.ListActivity{}).Count(&cnt).Error; err != nil {
		panic(err)
	}

	totalpages := cnt / 50
	if cnt%50 != 0 {
		totalpages++
	}

	if page > totalpages {
		page = totalpages
	}

	var activities []models.ListActivity
	if err := models.DB.Limit(limit).Offset((page - 1) * limit).Order("created_at desc").Find(&activities).Error; err != nil && err != gorm.ErrRecordNotFound {
		panic(err)
	}

	// render a better karma view
	var rendered []*activityJSON
	for _, v := range activities {
		// load the username...
		rendered = append(rendered, &activityJSON{
			ListId:  v.ListID,
			User:    models.FindUserByID(v.UserID).Username,
			Comment: string(bluemonday.UGCPolicy().SanitizeBytes(blackfriday.MarkdownCommon([]byte(v.Activity)))),
			Time:    v.CreatedAt,
			URL:     render.ConvertURL("/b/" + to.String(v.ListID)),
		})
	}

	dataRenderer.Data = map[string]interface{}{
		"totalpages": totalpages,
		"page":       page,
		"activities": rendered,
	}
	dataRenderer.Type = data.DataJSON
}
コード例 #6
0
ファイル: integration.go プロジェクト: robxu9/kahinah
// IntegrationHandler handles webhooks to integration handlers in the integration
// package by calling their hook function with the request.
func IntegrationHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	// integration is push only with status code returns. no response output.
	dataRender := data.FromContext(ctx)
	dataRender.Type = data.DataNoRender

	// get the handler name (as the first part)
	handlerName := pattern.Path(ctx)
	impl := integration.Implementations[strings.Split(handlerName, "/")[0]]

	if impl == nil {
		http.NotFound(rw, r)
	}

	impl.Hook(r)

	rw.WriteHeader(200)
}
コード例 #7
0
ファイル: static.go プロジェクト: robxu9/kahinah
func StaticHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	file := pattern.Path(ctx)

	f, err := staticDir.Open(file)
	if err != nil {
		panic(ErrNotFound) // assume not found
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		panic(err) // this is weird
	}

	// try to serve index file
	if fi.IsDir() {
		// redirect if missing trailing slash
		if !strings.HasSuffix(r.URL.Path, "/") {
			http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound)
			return
		}

		file = path.Join(file, indexFile)
		f, err = staticDir.Open(file)
		if err != nil {
			panic(ErrNotFound) // just hide its existence
		}
		defer f.Close()

		fi, err = f.Stat()
		if err != nil || fi.IsDir() {
			panic(ErrNotFound) // go away
		}
	}

	// okay, we don't need to render this.
	dataRender := data.FromContext(ctx)
	dataRender.Type = data.DataNoRender

	http.ServeContent(rw, r, file, fi.ModTime(), f)
}
コード例 #8
0
ファイル: builds.go プロジェクト: robxu9/kahinah
// ListsHandler shows the collection of lists (HTML).
func ListsHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)

	// filters that will be passed on by Vue.js to the API
	platform := r.FormValue("platform")
	channel := r.FormValue("channel")
	status := r.FormValue("status")
	limit := r.FormValue("limit")
	page := r.FormValue("page")

	dataRenderer.Data = map[string]interface{}{
		"Title":    "Lists",
		"Nav":      2,
		"Platform": platform,
		"Channel":  channel,
		"Status":   status,
		"Limit":    limit,
		"Page":     page,
	}
	dataRenderer.Template = "i/list"
}
コード例 #9
0
ファイル: builds.go プロジェクト: robxu9/kahinah
// BuildGetHandler displays build information for a specific build
func BuildGetHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)

	toRender := map[string]interface{}{}

	id := to.Uint64(pat.Param(ctx, "id"))

	var pkg models.List
	if err := models.DB.Where("id = ?", id).First(&pkg).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			panic(ErrNotFound)
		} else {
			panic(err)
		}
	}

	toRender["Title"] = "Build " + to.String(id) + ": " + pkg.Name
	toRender["Nav"] = 2
	toRender["ID"] = to.String(id)

	dataRenderer.Data = toRender
	dataRenderer.Template = "builds/build"
}
コード例 #10
0
ファイル: admin.go プロジェクト: robxu9/kahinah
// AdminGetHandler controls the central dashboard for Kahinah.
func AdminGetHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	adminCheck(r)

	dataRenderer := data.FromContext(ctx)

	toRender := map[string]interface{}{
		"Loc":   0,
		"Tab":   -1,
		"Title": "Admin",
	}

	user := r.FormValue("username")
	if user != "" {
		userModel := models.FindUser(user)
		toRender["User"] = userModel
	}

	var perms []models.UserPermission
	if err := models.DB.Find(&perms).Error; err != nil && err != gorm.ErrRecordNotFound {
		panic(err)
	}

	rendered := map[string][]string{}

	for _, perm := range perms {
		if _, ok := rendered[perm.Permission]; !ok {
			rendered[perm.Permission] = []string{}
		}
		rendered[perm.Permission] = append(rendered[perm.Permission], models.FindUserByID(perm.UserID).Username)
	}

	toRender["Permissions"] = rendered

	dataRenderer.Data = toRender
	dataRenderer.Template = "admin"
}
コード例 #11
0
ファイル: builds.go プロジェクト: robxu9/kahinah
// ListsAPIHandler shows the collection of lists, with filters, paginated, JSON'ified.
func ListsAPIHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)
	dataRenderer.Type = data.DataJSON

	platform := r.FormValue("platform")
	channel := r.FormValue("channel")
	status := r.FormValue("status")

	limit := int(to.Int64(r.FormValue("limit")))
	if limit <= 0 {
		limit = 50 // reasonable
	}

	page := int(to.Int64(r.FormValue("page")))
	if page <= 0 {
		page = 1
	}

	baseDB := models.DB.Model(&models.List{})
	if platform != "" {
		baseDB = baseDB.Where("platform = ?", platform)
	}

	if channel != "" {
		baseDB = baseDB.Where("channel = ?", channel)
	}

	if status == models.ListRunning || status == models.ListPending || status == models.ListSuccess || status == models.ListFailed {
		baseDB = baseDB.Where("stage_result = ?", status)
	} else if status != "" {
		panic(ErrBadRequest)
	}

	var cnt int
	if err := baseDB.Count(&cnt).Error; err != nil {
		panic(err)
	}

	totalpages := cnt / limit
	if cnt%limit != 0 {
		totalpages++
	}

	if page > totalpages {
		page = totalpages
	}

	var packages []*models.List
	if err := baseDB.Limit(limit).Offset((page - 1) * limit).Order("updated_at desc").Find(&packages).Error; err != nil && err != gorm.ErrRecordNotFound {
		panic(err)
	}

	dataRenderer.Data = map[string]interface{}{
		"lists": packages,
		"pages": map[string]interface{}{
			"prev":    page - 1,
			"current": page,
			"next":    page + 1,
			"total":   totalpages,
		},
	}
}
コード例 #12
0
ファイル: builds.go プロジェクト: robxu9/kahinah
// BuildPostHandler handles post actions that occur to the current active stage.
func BuildPostHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	// check for authentication
	user := models.FindUser(MustAuthenticate(r))

	// setup
	dataRenderer := data.FromContext(ctx)

	// read parameters
	id := to.Uint64(pat.Param(ctx, "id"))
	target := r.FormValue("target") // either activity or process
	name := r.FormValue("name")     // activity (ignored), process - find process
	action := r.FormValue("action") // activity (ignored), process passed on
	value := r.FormValue("value")   // activity (comment), process passed on

	// find the build list
	var pkg models.List
	if err := models.DB.Where("id = ?", id).First(&pkg).Related(&pkg.Stages, "Stages").Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			panic(ErrNotFound)
		} else {
			panic(err)
		}
	}

	var result interface{}

	// act based on target
	switch target {
	case "activity":
		if value == "" {
			panic(ErrBadRequest)
		}
		pkg.AddActivity(user, value)
		result = map[string]interface{}{
			"success": true,
		}
	case "process":
		// load up the stage & process
		if err := models.DB.Related(&pkg.Stages, "Stages").Error; err != nil {
			panic(err)
		}
		var currentStage *models.ListStage
		for _, v := range pkg.Stages {
			if v.Name == pkg.StageCurrent {
				currentStage = &v
				break
			}
		}

		if currentStage == nil {
			panic(ErrNoCurrentStage)
		}

		if err := models.DB.Related(&currentStage.Processes).Error; err != nil {
			panic(err)
		}

		var selectedProcess *models.ListStageProcess
		for _, v := range currentStage.Processes {
			if v.Name == name {
				selectedProcess = &v
				break
			}
		}

		if selectedProcess == nil {
			panic(ErrBadRequest)
		}

		// initialise the process
		process, err := processes.BuildProcess(selectedProcess)
		if err != nil {
			panic(err)
		}

		r, err := process.APIRequest(user, action, value)
		if err != nil {
			result = map[string]interface{}{
				"error":   true,
				"message": err.Error(),
				"result":  r,
			}
		} else {
			result = r
		}
	default:
		panic(ErrBadRequest)
	}

	dataRenderer.Type = data.DataJSON
	dataRenderer.Data = result

	//http.Redirect(rw, r, r.URL.String(), http.StatusTemporaryRedirect)
}
コード例 #13
0
ファイル: builds.go プロジェクト: robxu9/kahinah
// BuildGetJSONHandler displays build information in JSON for a specific build.
func BuildGetJSONHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	dataRenderer := data.FromContext(ctx)
	id := to.Uint64(pat.Param(ctx, "id"))
	user := models.FindUserNoCreate(Authenticated(r))

	// load the requested build list
	var pkg models.List
	if err := models.DB.Where("id = ?", id).First(&pkg).Related(&pkg.Activity, "Activity").Related(&pkg.Artifacts, "Artifacts").Related(&pkg.Links, "Links").Related(&pkg.Stages, "Stages").Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			panic(ErrNotFound)
		} else {
			panic(err)
		}
	}

	// load stage information
	var stageInfo []buildGetJSONStage

	for _, v := range pkg.Stages {
		if err := models.DB.Related(&v.Processes, "Processes").Error; err != nil && err != gorm.ErrRecordNotFound {
			panic(err)
		}

		// get all process info
		status := map[string]processes.ProcessStatus{}
		metadata := map[string]interface{}{}
		optional := map[string]bool{}

		for _, p := range v.Processes {
			process, err := processes.BuildProcess(&p)
			if err != nil {
				panic(err)
			}

			status[p.Name] = process.Status()
			metadata[p.Name] = process.APIMetadata(user)
			optional[p.Name] = p.Optional
		}

		stageInfo = append(stageInfo, buildGetJSONStage{
			Name:     v.Name,
			Status:   status,
			Metadata: metadata,
			Optional: optional,
		})
	}

	// render the data in a nice way

	dataRenderer.Data = &buildGetJSON{
		ID:       pkg.ID,
		Platform: pkg.Platform,
		Channel:  pkg.Channel,
		Variants: strings.Split(pkg.Variants, ";"),
		Name:     pkg.Name,

		Artifacts: pkg.Artifacts,
		Links:     pkg.Links,
		Activity:  pkg.Activity,
		Changes:   pkg.Changes,

		BuildDate: pkg.BuildDate,
		Updated:   pkg.UpdatedAt,

		PlatformConfig: pkg.PlatformGitConfig,
		Stages:         stageInfo,
		CurrentStage:   pkg.StageCurrent,
		Status:         pkg.StageResult,
		Advisory:       pkg.AdvisoryID,
	}
	dataRenderer.Type = data.DataJSON
}