Stat repo scoping
Statistical queries are now scoped to repos that user have access to
This commit is contained in:
parent
fc4a95545d
commit
34ca694242
33
db/stat.go
33
db/stat.go
|
@ -30,7 +30,7 @@ join users u on
|
||||||
join repos r on
|
join repos r on
|
||||||
c.repo_id = r.id`
|
c.repo_id = r.id`
|
||||||
|
|
||||||
func StatOrgTop(p map[string]interface{}) (res []StatItem) {
|
func StatOrgTop(login string, p map[string]interface{}) (res []StatItem) {
|
||||||
defer measure(time.Now(), "StatOrgTop")
|
defer measure(time.Now(), "StatOrgTop")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -41,6 +41,7 @@ func StatOrgTop(p map[string]interface{}) (res []StatItem) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
group by item
|
group by item
|
||||||
|
@ -49,7 +50,7 @@ func StatOrgTop(p map[string]interface{}) (res []StatItem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatOrgActivity(p map[string]interface{}) (res []StatPoint) {
|
func StatOrgActivity(login string, p map[string]interface{}) (res []StatPoint) {
|
||||||
defer measure(time.Now(), "StatOrgActivity")
|
defer measure(time.Now(), "StatOrgActivity")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -61,6 +62,7 @@ func StatOrgActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
group by item, week
|
group by item, week
|
||||||
|
@ -69,7 +71,7 @@ func StatOrgActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatTeamTop(p map[string]interface{}) (res []StatItem) {
|
func StatTeamTop(login string, p map[string]interface{}) (res []StatItem) {
|
||||||
defer measure(time.Now(), "StatTeamTop")
|
defer measure(time.Now(), "StatTeamTop")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -80,6 +82,7 @@ func StatTeamTop(p map[string]interface{}) (res []StatItem) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
t.name = :team and
|
t.name = :team and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -89,7 +92,7 @@ func StatTeamTop(p map[string]interface{}) (res []StatItem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatTeamActivity(p map[string]interface{}) (res []StatPoint) {
|
func StatTeamActivity(login string, p map[string]interface{}) (res []StatPoint) {
|
||||||
defer measure(time.Now(), "StatTeamActivity")
|
defer measure(time.Now(), "StatTeamActivity")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -101,6 +104,7 @@ func StatTeamActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
t.name = :team and
|
t.name = :team and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -110,7 +114,7 @@ func StatTeamActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatUserTop(p map[string]interface{}) (res []StatItem) {
|
func StatUserTop(login string, p map[string]interface{}) (res []StatItem) {
|
||||||
defer measure(time.Now(), "StatUserTop")
|
defer measure(time.Now(), "StatUserTop")
|
||||||
mustSelectN(&res, `
|
mustSelectN(&res, `
|
||||||
select
|
select
|
||||||
|
@ -126,6 +130,7 @@ func StatUserTop(p map[string]interface{}) (res []StatItem) {
|
||||||
c.repo_id = r.id
|
c.repo_id = r.id
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
u.login = :user and
|
u.login = :user and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -135,7 +140,7 @@ func StatUserTop(p map[string]interface{}) (res []StatItem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatUserActivity(p map[string]interface{}) (res []StatPoint) {
|
func StatUserActivity(login string, p map[string]interface{}) (res []StatPoint) {
|
||||||
defer measure(time.Now(), "StatUserActivity")
|
defer measure(time.Now(), "StatUserActivity")
|
||||||
mustSelectN(&res, `
|
mustSelectN(&res, `
|
||||||
select
|
select
|
||||||
|
@ -152,6 +157,7 @@ func StatUserActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
c.repo_id = r.id
|
c.repo_id = r.id
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
u.login = :user and
|
u.login = :user and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -161,7 +167,7 @@ func StatUserActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatRepoTop(p map[string]interface{}) (res []StatItem) {
|
func StatRepoTop(login string, p map[string]interface{}) (res []StatItem) {
|
||||||
defer measure(time.Now(), "StatRepoTop")
|
defer measure(time.Now(), "StatRepoTop")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -172,6 +178,7 @@ func StatRepoTop(p map[string]interface{}) (res []StatItem) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
r.name = :repo and
|
r.name = :repo and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -181,7 +188,7 @@ func StatRepoTop(p map[string]interface{}) (res []StatItem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatRepoActivity(p map[string]interface{}) (res []StatPoint) {
|
func StatRepoActivity(login string, p map[string]interface{}) (res []StatPoint) {
|
||||||
defer measure(time.Now(), "StatRepoActivity")
|
defer measure(time.Now(), "StatRepoActivity")
|
||||||
mustSelectN(&res, fmt.Sprintf(`
|
mustSelectN(&res, fmt.Sprintf(`
|
||||||
select
|
select
|
||||||
|
@ -193,6 +200,7 @@ func StatRepoActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
`+joinContribFT+`
|
`+joinContribFT+`
|
||||||
where
|
where
|
||||||
o.login = :org and
|
o.login = :org and
|
||||||
|
c.repo_id in `+reposScope(login)+` and
|
||||||
r.name = :repo and
|
r.name = :repo and
|
||||||
c.week >= :from and
|
c.week >= :from and
|
||||||
c.week <= :to
|
c.week <= :to
|
||||||
|
@ -201,3 +209,12 @@ func StatRepoActivity(p map[string]interface{}) (res []StatPoint) {
|
||||||
`, p["item"]), p)
|
`, p["item"]), p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reposScope(login string) string {
|
||||||
|
return fmt.Sprintf(`(
|
||||||
|
select repo_id
|
||||||
|
from team_repos tr
|
||||||
|
join team_members tm on tr.team_id = tm.team_id
|
||||||
|
join users u on u.login = %q
|
||||||
|
)`, login)
|
||||||
|
}
|
||||||
|
|
|
@ -6,25 +6,25 @@ import (
|
||||||
"github.com/localhots/empact/db"
|
"github.com/localhots/empact/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiOrgsHandler(w http.ResponseWriter, r *http.Request) {
|
func apiUserOrgsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, _ := parseRequest(w, r)
|
req, _ := parseRequest(w, r)
|
||||||
orgs := db.UserOrgs(req.login)
|
orgs := db.UserOrgs(req.login)
|
||||||
req.respondWith(orgs)
|
req.respondWith(orgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiTeamsHandler(w http.ResponseWriter, r *http.Request) {
|
func apiOrgTeamsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
teams := db.OrgTeams(stat.Org)
|
teams := db.OrgTeams(stat.Org)
|
||||||
req.respondWith(teams)
|
req.respondWith(teams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiUsersHandler(w http.ResponseWriter, r *http.Request) {
|
func apiOrgUsersHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
users := db.OrgUsers(stat.Org)
|
users := db.OrgUsers(stat.Org)
|
||||||
req.respondWith(users)
|
req.respondWith(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiReposHandler(w http.ResponseWriter, r *http.Request) {
|
func apiOrgReposHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
repos := db.OrgRepos(stat.Org)
|
repos := db.OrgRepos(stat.Org)
|
||||||
req.respondWith(repos)
|
req.respondWith(repos)
|
||||||
|
|
|
@ -41,7 +41,14 @@ func parseRequest(w http.ResponseWriter, r *http.Request) (*request, *statReques
|
||||||
token: token,
|
token: token,
|
||||||
login: login,
|
login: login,
|
||||||
}
|
}
|
||||||
return req, parseStatRequest(r)
|
sr := parseStatRequest(r)
|
||||||
|
|
||||||
|
// XXX: Hack for demo account
|
||||||
|
if req.login == "" {
|
||||||
|
req.login = "andrewarrow"
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, sr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *request) authorize(token, login string) {
|
func (r *request) authorize(token, login string) {
|
||||||
|
|
|
@ -22,10 +22,10 @@ func init() {
|
||||||
http.HandleFunc("/auth/callback", authCallbackHandler)
|
http.HandleFunc("/auth/callback", authCallbackHandler)
|
||||||
|
|
||||||
http.HandleFunc("/api/", authHandler)
|
http.HandleFunc("/api/", authHandler)
|
||||||
http.HandleFunc("/api/orgs", apiOrgsHandler)
|
http.HandleFunc("/api/orgs", apiUserOrgsHandler)
|
||||||
http.HandleFunc("/api/teams", apiTeamsHandler)
|
http.HandleFunc("/api/teams", apiOrgTeamsHandler)
|
||||||
http.HandleFunc("/api/users", apiUsersHandler)
|
http.HandleFunc("/api/users", apiOrgUsersHandler)
|
||||||
http.HandleFunc("/api/repos", apiReposHandler)
|
http.HandleFunc("/api/repos", apiOrgReposHandler)
|
||||||
http.HandleFunc("/api/weeks", apiOrgWeekRangeHandler)
|
http.HandleFunc("/api/weeks", apiOrgWeekRangeHandler)
|
||||||
|
|
||||||
http.HandleFunc("/api/stat/orgs/top", statOrgTopHandler)
|
http.HandleFunc("/api/stat/orgs/top", statOrgTopHandler)
|
||||||
|
|
|
@ -9,48 +9,48 @@ import (
|
||||||
|
|
||||||
func statOrgTopHandler(w http.ResponseWriter, r *http.Request) {
|
func statOrgTopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
top := db.StatOrgTop(structs.Map(stat))
|
top := db.StatOrgTop(req.login, structs.Map(stat))
|
||||||
req.respondWith(top)
|
req.respondWith(top)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statOrgActivityHandler(w http.ResponseWriter, r *http.Request) {
|
func statOrgActivityHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
activity := db.StatOrgActivity(structs.Map(stat))
|
activity := db.StatOrgActivity(req.login, structs.Map(stat))
|
||||||
req.respondWith(activity)
|
req.respondWith(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statTeamTopHandler(w http.ResponseWriter, r *http.Request) {
|
func statTeamTopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
top := db.StatTeamTop(structs.Map(stat))
|
top := db.StatTeamTop(req.login, structs.Map(stat))
|
||||||
req.respondWith(top)
|
req.respondWith(top)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statTeamActivityHandler(w http.ResponseWriter, r *http.Request) {
|
func statTeamActivityHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
activity := db.StatTeamActivity(structs.Map(stat))
|
activity := db.StatTeamActivity(req.login, structs.Map(stat))
|
||||||
req.respondWith(activity)
|
req.respondWith(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statUserTopHandler(w http.ResponseWriter, r *http.Request) {
|
func statUserTopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
top := db.StatUserTop(structs.Map(stat))
|
top := db.StatUserTop(req.login, structs.Map(stat))
|
||||||
req.respondWith(top)
|
req.respondWith(top)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statUserActivityHandler(w http.ResponseWriter, r *http.Request) {
|
func statUserActivityHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
activity := db.StatUserActivity(structs.Map(stat))
|
activity := db.StatUserActivity(req.login, structs.Map(stat))
|
||||||
req.respondWith(activity)
|
req.respondWith(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statRepoTopHandler(w http.ResponseWriter, r *http.Request) {
|
func statRepoTopHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
top := db.StatRepoTop(structs.Map(stat))
|
top := db.StatRepoTop(req.login, structs.Map(stat))
|
||||||
req.respondWith(top)
|
req.respondWith(top)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statRepoActivityHandler(w http.ResponseWriter, r *http.Request) {
|
func statRepoActivityHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
req, stat := parseRequest(w, r)
|
req, stat := parseRequest(w, r)
|
||||||
activity := db.StatRepoActivity(structs.Map(stat))
|
activity := db.StatRepoActivity(req.login, structs.Map(stat))
|
||||||
req.respondWith(activity)
|
req.respondWith(activity)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue