Skip to content

Commit 8e86149

Browse files
committed
Permissions page for template perms
1 parent 7ce87a7 commit 8e86149

File tree

13 files changed

+87
-27
lines changed

13 files changed

+87
-27
lines changed

coderd/apidoc/docs.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codersdk/templates.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ type UpdateTemplateACL struct {
170170
// ACLAvailable is a list of users and groups that can be added to a template
171171
// ACL.
172172
type ACLAvailable struct {
173-
Users []MinimalUser `json:"users"`
173+
Users []User `json:"users"`
174174
Groups []Group `json:"groups"`
175175
}
176176

docs/api/enterprise.md

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/api/schemas.md

Lines changed: 16 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

enterprise/coderd/templates.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,22 @@ func (api *API) templateAvailablePermissions(rw http.ResponseWriter, r *http.Req
5757

5858
sdkGroups := make([]codersdk.Group, 0, len(groups))
5959
for _, group := range groups {
60-
sdkGroups = append(sdkGroups, codersdk.Group{
61-
ID: group.ID,
62-
Name: group.Name,
63-
OrganizationID: group.OrganizationID,
64-
AvatarURL: group.AvatarURL,
65-
QuotaAllowance: int(group.QuotaAllowance),
66-
})
60+
// nolint:gocritic
61+
members, err := api.Database.GetGroupMembers(dbauthz.AsSystemRestricted(ctx), group.ID)
62+
if err != nil {
63+
httpapi.InternalServerError(rw, err)
64+
return
65+
}
66+
67+
sdkGroups = append(sdkGroups, convertGroup(group, members))
6768
}
6869

6970
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ACLAvailable{
70-
Users: convertMinimalUser(users),
71+
// No need to pass organization info here.
72+
// TODO: @emyrk we should return a MinimalUser here instead of a full user.
73+
// The FE requires the `email` field, so this cannot be done without
74+
// a UI change.
75+
Users: convertUsers(users, map[uuid.UUID][]uuid.UUID{}),
7176
Groups: sdkGroups,
7277
})
7378
}

site/src/api/api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,15 @@ export const getDeploymentDAUs = async (
869869
return response.data
870870
}
871871

872+
export const getTemplateACLAvailable = async (
873+
templateId: string,
874+
options: TypesGen.UsersRequest,
875+
): Promise<TypesGen.ACLAvailable> => {
876+
const url = getURLWithSearchParams(`/api/v2/templates/${templateId}/acl/available`, options)
877+
const response = await axios.get(url.toString())
878+
return response.data
879+
}
880+
872881
export const getTemplateACL = async (
873882
templateId: string,
874883
): Promise<TypesGen.TemplateACL> => {

site/src/api/typesGenerated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
// From codersdk/templates.go
44
export interface ACLAvailable {
5-
readonly users: MinimalUser[]
5+
readonly users: User[]
66
readonly groups: Group[]
77
}
88

site/src/components/UserOrGroupAutocomplete/UserOrGroupAutocomplete.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,21 @@ export type UserOrGroupAutocompleteProps = {
2121
value: UserOrGroupAutocompleteValue
2222
onChange: (value: UserOrGroupAutocompleteValue) => void
2323
organizationId: string
24+
templateID?: string
2425
exclude: UserOrGroupAutocompleteValue[]
2526
}
2627

2728
export const UserOrGroupAutocomplete: React.FC<
2829
UserOrGroupAutocompleteProps
29-
> = ({ value, onChange, organizationId, exclude }) => {
30+
> = ({ value, onChange, organizationId, templateID, exclude }) => {
3031
const styles = useStyles()
3132
const [isAutocompleteOpen, setIsAutocompleteOpen] = useState(false)
3233
const [searchState, sendSearch] = useMachine(searchUsersAndGroupsMachine, {
3334
context: {
3435
userResults: [],
3536
groupResults: [],
3637
organizationId,
38+
templateID,
3739
},
3840
})
3941
const { userResults, groupResults } = searchState.context
@@ -73,6 +75,7 @@ export const UserOrGroupAutocomplete: React.FC<
7375
}
7476
renderOption={(props, option) => {
7577
const isOptionGroup = isGroup(option)
78+
console.log("option", option)
7679

7780
return (
7881
<Box component="li" {...props}>

site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export const TemplatePermissionsPage: FC<
6464
<Cond>
6565
<TemplatePermissionsPageView
6666
organizationId={organizationId}
67+
templateID={template.id}
6768
templateACL={templateACL}
6869
canUpdatePermissions={Boolean(permissions?.canUpdateTemplate)}
6970
onAddUser={(user, role, reset) => {

site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPageView.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"
3434

3535
type AddTemplateUserOrGroupProps = {
3636
organizationId: string
37+
templateID: string
3738
isLoading: boolean
3839
templateACL: TemplateACL | undefined
3940
onSubmit: (
@@ -47,6 +48,7 @@ const AddTemplateUserOrGroup: React.FC<AddTemplateUserOrGroupProps> = ({
4748
isLoading,
4849
onSubmit,
4950
organizationId,
51+
templateID,
5052
templateACL,
5153
}) => {
5254
const styles = useStyles()
@@ -83,6 +85,7 @@ const AddTemplateUserOrGroup: React.FC<AddTemplateUserOrGroupProps> = ({
8385
<UserOrGroupAutocomplete
8486
exclude={excludeFromAutocomplete}
8587
organizationId={organizationId}
88+
templateID={templateID}
8689
value={selectedOption}
8790
onChange={(newValue) => {
8891
setSelectedOption(newValue)
@@ -151,6 +154,7 @@ const RoleSelect: FC<SelectProps> = (props) => {
151154

152155
export interface TemplatePermissionsPageViewProps {
153156
templateACL: TemplateACL | undefined
157+
templateID: string
154158
organizationId: string
155159
canUpdatePermissions: boolean
156160
// User
@@ -177,6 +181,7 @@ export const TemplatePermissionsPageView: FC<
177181
templateACL,
178182
canUpdatePermissions,
179183
organizationId,
184+
templateID,
180185
// User
181186
onAddUser,
182187
isAddingUser,
@@ -207,6 +212,7 @@ export const TemplatePermissionsPageView: FC<
207212
<Maybe condition={canUpdatePermissions}>
208213
<AddTemplateUserOrGroup
209214
templateACL={templateACL}
215+
templateID={templateID}
210216
organizationId={organizationId}
211217
isLoading={isAddingUser || isAddingGroup}
212218
onSubmit={(value, role, resetAutocomplete) =>

site/src/utils/groups.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ export const getGroupSubtitle = (group: Group): string => {
1515
return `All users`
1616
}
1717

18+
if(!group.members) {
19+
return `0 members`
20+
}
21+
1822
if (group.members.length === 1) {
1923
return `1 member`
2024
}

site/src/xServices/template/searchUsersAndGroupsXService.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getGroups, getUsers } from "api/api"
1+
import { getGroups, getTemplateACLAvailable, getUsers } from "api/api"
22
import { Group, User } from "api/typesGenerated"
33
import { queryToFilter } from "utils/filters"
44
import { everyOneGroup } from "utils/groups"
@@ -15,6 +15,7 @@ export const searchUsersAndGroupsMachine = createMachine(
1515
schema: {
1616
context: {} as {
1717
organizationId: string
18+
templateID?: string
1819
userResults: User[]
1920
groupResults: Group[]
2021
},
@@ -56,16 +57,26 @@ export const searchUsersAndGroupsMachine = createMachine(
5657
},
5758
{
5859
services: {
59-
search: async ({ organizationId }, { query }) => {
60-
const [userRes, groups] = await Promise.all([
61-
getUsers(queryToFilter(query)),
62-
getGroups(organizationId),
63-
])
60+
search: async ({ organizationId, templateID }, { query }) => {
61+
let users, groups
62+
if(templateID && templateID !== "") {
63+
const res = await getTemplateACLAvailable(templateID, queryToFilter(query))
64+
users = res.users
65+
groups = res.groups
66+
} else {
67+
const [userRes, groupsRes] = await Promise.all([
68+
getUsers(queryToFilter(query)),
69+
getGroups(organizationId),
70+
])
71+
72+
users = userRes.users
73+
groups = groupsRes
74+
}
6475

6576
// The Everyone groups is not returned by the API so we have to add it
6677
// manually
6778
return {
68-
users: userRes.users,
79+
users: users,
6980
groups: [everyOneGroup(organizationId), ...groups],
7081
}
7182
},

0 commit comments

Comments
 (0)