Skip to content

Commit

Permalink
feat(ui): hide functionality from unpriv persons (#548)
Browse files Browse the repository at this point in the history
Hide rather than show and disable.

Fixes #540
  • Loading branch information
leg100 authored Aug 1, 2023
1 parent abfc702 commit fee491f
Show file tree
Hide file tree
Showing 24 changed files with 283 additions and 255 deletions.
18 changes: 13 additions & 5 deletions internal/auth/team_web.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ func (h *webHandlers) getTeam(w http.ResponseWriter, r *http.Request) {
Team *Team
Members []*User
AddMemberDropdown html.DropdownUI
CanUpdateTeam bool
CanDeleteTeam bool
CanAddMember bool
CanRemoveMember bool
CanDelete bool
Expand All @@ -125,6 +127,8 @@ func (h *webHandlers) getTeam(w http.ResponseWriter, r *http.Request) {
OrganizationPage: organization.NewPage(r, team.ID, team.Organization),
Team: team,
Members: members,
CanUpdateTeam: user.CanAccessOrganization(rbac.UpdateTeamAction, team.Organization),
CanDeleteTeam: user.CanAccessOrganization(rbac.DeleteTeamAction, team.Organization),
CanAddMember: user.CanAccessOrganization(rbac.AddTeamMembershipAction, team.Organization),
CanRemoveMember: user.CanAccessOrganization(rbac.RemoveTeamMembershipAction, team.Organization),
CanDelete: user.CanAccessOrganization(rbac.DeleteTeamAction, team.Organization),
Expand Down Expand Up @@ -173,16 +177,20 @@ func (h *webHandlers) listTeams(w http.ResponseWriter, r *http.Request) {
return
}

user, err := UserFromContext(r.Context())
if err != nil {
h.Error(w, err.Error(), http.StatusInternalServerError)
return
}

h.Render("team_list.tmpl", w, struct {
organization.OrganizationPage
Teams []*Team
CreateTeamAction rbac.Action
DeleteTeamAction rbac.Action
Teams []*Team
CanCreateTeam bool
}{
OrganizationPage: organization.NewPage(r, "teams", org),
Teams: teams,
CreateTeamAction: rbac.CreateTeamAction,
DeleteTeamAction: rbac.DeleteTeamAction,
CanCreateTeam: user.CanAccessOrganization(rbac.CreateTeamAction, org),
})
}

Expand Down
9 changes: 0 additions & 9 deletions internal/http/html/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@ func nextPageQuery(p resource.Pagination) *string {
return internal.String(fmt.Sprintf("page[number]=%d", *p.NextPage))
}

// insufficient returns form attributes that disable the form element and
// notify the user they have insufficent permissions if they lack a permission
func insufficient(can bool) template.HTMLAttr {
if !can {
return `title="insufficient permissions" disabled`
}
return ""
}

func disabled(arg any, args ...any) (template.HTMLAttr, error) {
return attrIf("disabled", arg, args...)
}
Expand Down
1 change: 0 additions & 1 deletion internal/http/html/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ func newTemplateCache(templates fs.FS, buster *cacheBuster, devMode bool) (map[s
funcs["selected"] = selected
funcs["checked"] = checked
funcs["disabled"] = disabled
funcs["insufficient"] = insufficient
funcs["devMode"] = func() bool { return devMode }
// make path helpers available to templates
for k, v := range paths.FuncMap() {
Expand Down
20 changes: 14 additions & 6 deletions internal/http/html/static/css/output.css
Original file line number Diff line number Diff line change
Expand Up @@ -923,8 +923,20 @@ th, td {
flex-grow: 1;
}

.basis-52 {
flex-basis: 13rem;
.basis-1\/5 {
flex-basis: 20%;
}

.basis-4\/5 {
flex-basis: 80%;
}

.basis-3\/5 {
flex-basis: 60%;
}

.basis-2\/5 {
flex-basis: 40%;
}

.table-fixed {
Expand Down Expand Up @@ -1293,10 +1305,6 @@ th, td {
--tw-shadow: var(--tw-shadow-colored);
}

.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.even\:bg-gray-100:nth-child(even) {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
Expand Down
8 changes: 5 additions & 3 deletions internal/http/html/static/templates/content/module_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
{{ define "content-header-title" }}modules{{ end }}

{{ define "content-header-actions" }}
<form action="{{ newModulePath .Organization }}" method="GET">
<button class="btn" id="list-module-vcs-providers-button">Publish</button>
</form>
{{ if .CanPublishModule }}
<form action="{{ newModulePath .Organization }}" method="GET">
<button class="btn" id="list-module-vcs-providers-button">Publish</button>
</form>
{{ end }}
{{ end }}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,19 @@
{{ define "content-header-title" }}settings{{ end }}

{{ define "content" }}
{{ $canUpdate := $.CurrentUser.CanAccessOrganization .UpdateOrganizationAction .Name }}
{{ $canDelete := $.CurrentUser.CanAccessOrganization .DeleteOrganizationAction .Name }}

<form class="flex flex-col gap-5" action="{{ updateOrganizationPath .Name }}" method="POST">
<div class="field">
<label for="name">Name</label>
<input class="text-input w-80" type="text" name="new_name" id="name" value="{{ .Name }}" required>
</div>
<div class="field">
<button class="btn w-72" {{ insufficient $canDelete }}>Update organization name</button>
<button class="btn w-72">Update organization name</button>
</div>
</form>
<hr class="my-4">
<h3 class="font-semibold text-lg mb-2">Advanced</h3>
<form action="{{ deleteOrganizationPath .Name }}" method="POST">
<button id="delete-organization-button" class="btn-danger" {{ insufficient $canDelete }} onclick="return confirm('Are you sure you want to delete?')">
<button id="delete-organization-button" class="btn-danger" onclick="return confirm('Are you sure you want to delete?')">
Delete organization
</button>
<input type="hidden" name="id" value="{{ .ID }}">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
<span id="organization_tokens">
<a href="{{ organizationTokenPath .Name }}">organization token</a>
</span>
{{ end }}
<span id="settings">
<a href="{{ editOrganizationPath .Name }}">settings</a>
</span>
{{ end }}
</div>
{{ end }}
132 changes: 64 additions & 68 deletions internal/http/html/static/templates/content/team_get.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,53 @@
{{ .Team.Name }}{{ end }}

{{ define "content" }}
<h3 class="font-semibold my-2 text-lg">Permissions</h3>
<form class="flex flex-col gap-5" action="{{ updateTeamPath .Team.ID }}" method="POST">
<div class="form-checkbox">
<input
type="checkbox"
name="manage_workspaces"
id="manage_workspaces"
value="true"
{{ if or .Team.OrganizationAccess.ManageWorkspaces .Team.IsOwners }}checked{{ end }}
{{ if or (not .IsOwner) .Team.IsOwners }}disabled{{ end }}
>
<label for="manage_workspaces">Manage Workspaces</label>
<span>Allows members to create and administrate all workspaces within the organization.</span>
</div>
<div class="form-checkbox">
<input
type="checkbox"
name="manage_vcs"
id="manage_vcs"
value="true"
{{ if or .Team.OrganizationAccess.ManageVCS .Team.IsOwners }}checked{{ end }}
{{ if or (not .IsOwner) .Team.IsOwners }}disabled{{ end }}
>
<label for="manage_vcs">Manage VCS Settings</label>
<span>Allows members to manage the set of VCS providers available within the organization.</span>
</div>
<div class="form-checkbox">
<input
type="checkbox"
name="manage_modules"
id="manage_modules"
value="true"
{{ if or .Team.OrganizationAccess.ManageModules .Team.IsOwners }}checked{{ end }}
{{ if or (not .IsOwner) .Team.IsOwners }}disabled{{ end }}
>
<label for="manage_modules">Manage Modules</label>
<span for="manage_modules">Allows members to publish and delete modules within the organization.</span>
</div>
<div class="field">
<button class="btn w-40"
{{ if .Team.IsOwners }}
title="cannot edit permissions of owners team" disabled
{{ else }}
{{ insufficient .IsOwner }}
{{ end }}
>Save changes</button>
</div>
</form>
<hr class="my-4">
{{ if .CanUpdateTeam }}
<h3 class="font-semibold my-2 text-lg">Permissions</h3>
<form class="flex flex-col gap-5" action="{{ updateTeamPath .Team.ID }}" method="POST">
<div class="form-checkbox">
<input
type="checkbox"
name="manage_workspaces"
id="manage_workspaces"
value="true"
{{ if or .Team.OrganizationAccess.ManageWorkspaces .Team.IsOwners }}checked{{ end }}
{{ if .Team.IsOwners }}title="cannot change permissions of owners team" disabled{{ end }}
>
<label for="manage_workspaces">Manage Workspaces</label>
<span>Allows members to create and administrate all workspaces within the organization.</span>
</div>
<div class="form-checkbox">
<input
type="checkbox"
name="manage_vcs"
id="manage_vcs"
value="true"
{{ if or .Team.OrganizationAccess.ManageVCS .Team.IsOwners }}checked{{ end }}
{{ if .Team.IsOwners }}title="cannot change permissions of owners team" disabled{{ end }}
>
<label for="manage_vcs">Manage VCS Settings</label>
<span>Allows members to manage the set of VCS providers available within the organization.</span>
</div>
<div class="form-checkbox">
<input
type="checkbox"
name="manage_modules"
id="manage_modules"
value="true"
{{ if or .Team.OrganizationAccess.ManageModules .Team.IsOwners }}checked{{ end }}
{{ if .Team.IsOwners }}title="cannot change permissions of owners team" disabled{{ end }}
>
<label for="manage_modules">Manage Modules</label>
<span for="manage_modules">Allows members to publish and delete modules within the organization.</span>
</div>
{{ if not .Team.IsOwners }}
<div class="field">
<button class="btn w-40">Save changes</button>
</div>
{{ end }}
</form>
<hr class="my-4">
{{ end }}
<h3 class="font-semibold my-2 text-lg">Members</h3>
{{ if .CanAddMember }}
{{ template "search-dropdown" .AddMemberDropdown }}
Expand All @@ -67,29 +65,27 @@
</div>
<div>
{{ template "identifier" . }}
<form action="{{ removeMemberTeamPath $.Team.ID }}" method="POST">
<input type="hidden" name="username" id="delete-username" value="{{ .Username }}">
<button id="remove-member-button" class="btn-danger" {{ insufficient $.CanRemoveMember }}>
Remove member
</button>
</form>
{{ if $.CanRemoveMember }}
<form action="{{ removeMemberTeamPath $.Team.ID }}" method="POST">
<input type="hidden" name="username" id="delete-username" value="{{ .Username }}">
<button id="remove-member-button" class="btn-danger">
Remove member
</button>
</form>
{{ end }}
</div>
</div>
{{ else }}
The team currently has no members.
{{ end }}
</div>
<hr class="my-4">
<h3 class="font-semibold my-2 text-lg">Advanced</h3>
<form action="{{ deleteTeamPath .Team.ID }}" method="POST">
<button
class="btn-danger"
{{ if .Team.IsOwners }}
title="the owners team cannot be deleted" disabled
{{ else }}
{{ insufficient .CanDelete }}
{{ end }}
onclick="return confirm('Are you sure you want to delete?')">Delete team</button>
<input type="hidden" name="id" value="{{ .Team.ID }}">
</form>
{{ if and (not .Team.IsOwners) .CanDeleteTeam }}
<hr class="my-4">
<h3 class="font-semibold my-2 text-lg">Advanced</h3>
<form action="{{ deleteTeamPath .Team.ID }}" method="POST">
<button class="btn-danger"
onclick="return confirm('Are you sure you want to delete?')">Delete team</button>
<input type="hidden" name="id" value="{{ .Team.ID }}">
</form>
{{ end }}
{{ end }}
13 changes: 7 additions & 6 deletions internal/http/html/static/templates/content/team_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
{{ define "content-header-title" }}teams{{ end }}

{{ define "content-header-actions" }}
{{ $canCreate := .CurrentUser.CanAccessOrganization .CreateTeamAction .Organization }}
<form action="{{ newTeamPath .Organization }}" method="GET">
<button class="btn" id="new-team-button" {{ insufficient $canCreate }}>
New Team
</button>
</form>
{{ if .CanCreateTeam }}
<form action="{{ newTeamPath .Organization }}" method="GET">
<button class="btn" id="new-team-button">
New Team
</button>
</form>
{{ end }}
{{ end }}

{{ define "content" }}
Expand Down
18 changes: 10 additions & 8 deletions internal/http/html/static/templates/content/variable_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
{{ end }}

{{ define "content" }}
{{ $canCreate := $.CurrentUser.CanAccessWorkspace .CreateVariableAction .Policy }}
{{ $canDelete := $.CurrentUser.CanAccessWorkspace .DeleteVariableAction .Policy }}
<table class="table-fixed w-full text-left break-words border-collapse" id="variables-table">
<thead class="bg-gray-200 border-t border-b border-slate-900">
<tr>
Expand All @@ -27,9 +25,11 @@
<td class="p-2">{{ if .Sensitive }}<span class="data">hidden</span>{{ else }}{{ .Value }}{{ end }}</td>
<td class="p-2">{{ .Category }}</td>
<td class="p-2 text-right">
<form action="{{ deleteVariablePath .ID }}" method="POST">
<button id="delete-variable-button" class="btn-danger" onclick="return confirm('Are you sure you want to delete?')" {{ insufficient $canDelete }} >Delete</button>
</form>
{{ if $.CanDeleteVariable }}
<form action="{{ deleteVariablePath .ID }}" method="POST">
<button id="delete-variable-button" class="btn-danger" onclick="return confirm('Are you sure you want to delete?')">Delete</button>
</form>
{{ end }}
</td>
</tr>
{{ else }}
Expand All @@ -39,7 +39,9 @@
{{ end }}
</tbody>
</table>
<form action="{{ newVariablePath $.Workspace.ID }}" method="GET">
<button class="btn" {{ insufficient $canCreate }}>Add variable</button>
</form>
{{ if .CanCreateVariable }}
<form action="{{ newVariablePath $.Workspace.ID }}" method="GET">
<button class="btn">Add variable</button>
</form>
{{ end }}
{{ end }}
Loading

0 comments on commit fee491f

Please sign in to comment.