Cap the number of personal projects per user

This commit is contained in:
Ben Visness 2021-12-08 22:02:11 -06:00
parent 79c9738b96
commit b88776af0c
3 changed files with 40 additions and 3 deletions

View File

@ -45,7 +45,11 @@
</div> </div>
{{ end }} {{ end }}
{{ if .OwnProfile }} {{ if .OwnProfile }}
<a href="{{ .NewProjectUrl }}">+ New Project</a> {{ if .CanAddProject }}
<a href="{{ .NewProjectUrl }}">+ New Project</a>
{{ else }}
<span class="c--dim i">You have reached the maximum number of personal projects.</span>
{{ end }}
{{ end }} {{ end }}
</div> </div>
{{ end }} {{ end }}

View File

@ -26,6 +26,8 @@ import (
"github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4"
) )
const maxPersonalProjects = 5
type ProjectTemplateData struct { type ProjectTemplateData struct {
templates.BaseData templates.BaseData
@ -387,6 +389,17 @@ type ProjectEditData struct {
} }
func ProjectNew(c *RequestContext) ResponseData { func ProjectNew(c *RequestContext) ResponseData {
numProjects, err := hmndata.CountProjects(c.Context(), c.Conn, c.CurrentUser, hmndata.ProjectsQuery{
OwnerIDs: []int{c.CurrentUser.ID},
Types: hmndata.PersonalProjects,
})
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to check number of personal projects"))
}
if numProjects >= maxPersonalProjects {
return RejectRequest(c, fmt.Sprintf("You have already reached the maximum of %d personal projects.", maxPersonalProjects))
}
var project templates.ProjectSettings var project templates.ProjectSettings
project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser, c.Theme)) project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser, c.Theme))
project.Personal = true project.Personal = true
@ -417,6 +430,17 @@ func ProjectNewSubmit(c *RequestContext) ResponseData {
} }
defer tx.Rollback(c.Context()) defer tx.Rollback(c.Context())
numProjects, err := hmndata.CountProjects(c.Context(), c.Conn, c.CurrentUser, hmndata.ProjectsQuery{
OwnerIDs: []int{c.CurrentUser.ID},
Types: hmndata.PersonalProjects,
})
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to check number of personal projects"))
}
if numProjects >= maxPersonalProjects {
return RejectRequest(c, fmt.Sprintf("You have already reached the maximum of %d personal projects.", maxPersonalProjects))
}
var projectId int var projectId int
err = tx.QueryRow(c.Context(), err = tx.QueryRow(c.Context(),
` `

View File

@ -29,7 +29,9 @@ type UserProfileTemplateData struct {
TimelineItems []templates.TimelineItem TimelineItems []templates.TimelineItem
OwnProfile bool OwnProfile bool
ShowcaseUrl string ShowcaseUrl string
NewProjectUrl string
CanAddProject bool
NewProjectUrl string
} }
func UserProfile(c *RequestContext) ResponseData { func UserProfile(c *RequestContext) ResponseData {
@ -108,10 +110,15 @@ func UserProfile(c *RequestContext) ResponseData {
projectsAndStuff, err := hmndata.FetchProjects(c.Context(), c.Conn, c.CurrentUser, projectsQuery) projectsAndStuff, err := hmndata.FetchProjects(c.Context(), c.Conn, c.CurrentUser, projectsQuery)
templateProjects := make([]templates.Project, 0, len(projectsAndStuff)) templateProjects := make([]templates.Project, 0, len(projectsAndStuff))
numPersonalProjects := 0
for _, p := range projectsAndStuff { for _, p := range projectsAndStuff {
templateProject := templates.ProjectToTemplate(&p.Project, hmndata.UrlContextForProject(&p.Project).BuildHomepage()) templateProject := templates.ProjectToTemplate(&p.Project, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
templateProject.AddLogo(p.LogoURL(c.Theme)) templateProject.AddLogo(p.LogoURL(c.Theme))
templateProjects = append(templateProjects, templateProject) templateProjects = append(templateProjects, templateProject)
if p.Project.Personal {
numPersonalProjects++
}
} }
c.Perf.EndBlock() c.Perf.EndBlock()
@ -182,7 +189,9 @@ func UserProfile(c *RequestContext) ResponseData {
TimelineItems: timelineItems, TimelineItems: timelineItems,
OwnProfile: (c.CurrentUser != nil && c.CurrentUser.ID == profileUser.ID), OwnProfile: (c.CurrentUser != nil && c.CurrentUser.ID == profileUser.ID),
ShowcaseUrl: hmnurl.BuildShowcase(), ShowcaseUrl: hmnurl.BuildShowcase(),
NewProjectUrl: hmnurl.BuildProjectNew(),
CanAddProject: numPersonalProjects < maxPersonalProjects,
NewProjectUrl: hmnurl.BuildProjectNew(),
}, c.Perf) }, c.Perf)
return res return res
} }