Skip to content

Commit 5060443

Browse files
committed
Merge remote-tracking branch 'origin/main' into stevenmasley/implied_member
2 parents 9a3d38e + 7acb742 commit 5060443

File tree

197 files changed

+768
-525
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+768
-525
lines changed

coderd/members.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {
2020
user := httpmw.UserParam(r)
2121
organization := httpmw.OrganizationParam(r)
2222
member := httpmw.OrganizationMemberParam(r)
23+
apiKey := httpmw.APIKey(r)
24+
25+
if apiKey.UserID == member.UserID {
26+
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
27+
Message: "You cannot change your own organization roles.",
28+
})
29+
return
30+
}
2331

2432
var params codersdk.UpdateRoles
2533
if !httpapi.Read(rw, r, &params) {

coderd/users.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,14 @@ func (api *API) putUserRoles(rw http.ResponseWriter, r *http.Request) {
474474
// User is the user to modify.
475475
user := httpmw.UserParam(r)
476476
roles := httpmw.UserAuthorizationRoles(r)
477+
apiKey := httpmw.APIKey(r)
478+
479+
if apiKey.UserID == user.ID {
480+
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
481+
Message: "You cannot change your own roles.",
482+
})
483+
return
484+
}
477485

478486
var params codersdk.UpdateRoles
479487
if !httpapi.Read(rw, r, &params) {

coderd/users_test.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,11 @@ func TestGrantRoles(t *testing.T) {
409409
t.Run("UpdateIncorrectRoles", func(t *testing.T) {
410410
t.Parallel()
411411
ctx := context.Background()
412+
var err error
413+
412414
admin := coderdtest.New(t, nil)
413415
first := coderdtest.CreateFirstUser(t, admin)
414416
member := coderdtest.CreateAnotherUser(t, admin, first.OrganizationID)
415-
memberUser, err := member.User(ctx, codersdk.Me)
416-
require.NoError(t, err, "member user")
417417

418418
_, err = admin.UpdateUserRoles(ctx, codersdk.Me, codersdk.UpdateRoles{
419419
Roles: []string{rbac.RoleOrgAdmin(first.OrganizationID)},
@@ -445,7 +445,7 @@ func TestGrantRoles(t *testing.T) {
445445
require.Error(t, err, "member cannot change other's roles")
446446
requireStatusCode(t, err, http.StatusForbidden)
447447

448-
_, err = member.UpdateUserRoles(ctx, memberUser.ID.String(), codersdk.UpdateRoles{
448+
_, err = member.UpdateUserRoles(ctx, first.UserID.String(), codersdk.UpdateRoles{
449449
Roles: []string{},
450450
})
451451
require.Error(t, err, "member cannot change any roles")
@@ -456,6 +456,18 @@ func TestGrantRoles(t *testing.T) {
456456
})
457457
require.Error(t, err, "member cannot change other's org roles")
458458
requireStatusCode(t, err, http.StatusForbidden)
459+
460+
_, err = admin.UpdateUserRoles(ctx, first.UserID.String(), codersdk.UpdateRoles{
461+
Roles: []string{},
462+
})
463+
require.Error(t, err, "admin cannot change self roles")
464+
requireStatusCode(t, err, http.StatusBadRequest)
465+
466+
_, err = admin.UpdateOrganizationMemberRoles(ctx, first.OrganizationID, first.UserID.String(), codersdk.UpdateRoles{
467+
Roles: []string{},
468+
})
469+
require.Error(t, err, "admin cannot change self org roles")
470+
requireStatusCode(t, err, http.StatusBadRequest)
459471
})
460472

461473
t.Run("FirstUserRoles", func(t *testing.T) {
@@ -503,7 +515,7 @@ func TestGrantRoles(t *testing.T) {
503515
require.NoError(t, err, "grant member admin role")
504516

505517
// Promote to org admin
506-
_, err = member.UpdateOrganizationMemberRoles(ctx, first.OrganizationID, codersdk.Me, codersdk.UpdateRoles{
518+
_, err = admin.UpdateOrganizationMemberRoles(ctx, first.OrganizationID, memberUser.ID.String(), codersdk.UpdateRoles{
507519
Roles: []string{
508520
// Promote to org admin
509521
rbac.RoleOrgAdmin(first.OrganizationID),

scripts/develop.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
22

33
set -euo pipefail
4+
set -x
45

56
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
67
PROJECT_ROOT=$(cd "$SCRIPT_DIR" && git rev-parse --show-toplevel)
@@ -28,6 +29,6 @@ export CODER_DEV_ADMIN_PASSWORD=password
2829
# Just a minor sleep to ensure the first user was created to make the member.
2930
sleep 2
3031
# || yes to always exit code 0. If this fails, whelp.
31-
go run cmd/coder/main.go users create --email=member@coder.com --username=member --password="${CODER_DEV_ADMIN_PASSWORD}" || yes
32+
go run cmd/coder/main.go users create --email=member@coder.com --username=member --password="${CODER_DEV_ADMIN_PASSWORD}" || true
3233
wait
3334
)

scripts/yarn_install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#
66
# Usage: yarn_install.sh [optional extra flags]
77

8-
set -euo pipefail
8+
set -eo pipefail
99

1010
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
1111
PROJECT_ROOT=$(cd "$SCRIPT_DIR" && git rev-parse --show-toplevel)

site/.eslintrc.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ rules:
114114
react/jsx-curly-brace-presence:
115115
- error
116116
- children: ignore
117+
# https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#eslint
118+
react/jsx-uses-react: "off"
119+
react/react-in-jsx-scope: "off"
117120
settings:
118121
react:
119122
version: detect

site/src/AppRouter.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react"
1+
import { FC, lazy, Suspense } from "react"
22
import { Route, Routes } from "react-router-dom"
33
import { AuthAndFrame } from "./components/AuthAndFrame/AuthAndFrame"
44
import { RequireAuth } from "./components/RequireAuth/RequireAuth"
@@ -8,23 +8,23 @@ import { NotFoundPage } from "./pages/404Page/404Page"
88
import { CliAuthenticationPage } from "./pages/CliAuthPage/CliAuthPage"
99
import { HealthzPage } from "./pages/HealthzPage/HealthzPage"
1010
import { LoginPage } from "./pages/LoginPage/LoginPage"
11-
import { AccountPage } from "./pages/SettingsPages/AccountPage/AccountPage"
12-
import { SecurityPage } from "./pages/SettingsPages/SecurityPage/SecurityPage"
13-
import { SSHKeysPage } from "./pages/SettingsPages/SSHKeysPage/SSHKeysPage"
1411
import { TemplatePage } from "./pages/TemplatePage/TemplatePage"
1512
import TemplatesPage from "./pages/TemplatesPage/TemplatesPage"
13+
import { AccountPage } from "./pages/UserSettingsPage/AccountPage/AccountPage"
14+
import { SecurityPage } from "./pages/UserSettingsPage/SecurityPage/SecurityPage"
15+
import { SSHKeysPage } from "./pages/UserSettingsPage/SSHKeysPage/SSHKeysPage"
1616
import { CreateUserPage } from "./pages/UsersPage/CreateUserPage/CreateUserPage"
1717
import { UsersPage } from "./pages/UsersPage/UsersPage"
1818
import { WorkspaceBuildPage } from "./pages/WorkspaceBuildPage/WorkspaceBuildPage"
1919
import { WorkspacePage } from "./pages/WorkspacePage/WorkspacePage"
2020
import { WorkspaceSchedulePage } from "./pages/WorkspaceSchedulePage/WorkspaceSchedulePage"
2121

22-
const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage"))
23-
const WorkspacesPage = React.lazy(() => import("./pages/WorkspacesPage/WorkspacesPage"))
24-
const CreateWorkspacePage = React.lazy(() => import("./pages/CreateWorkspacePage/CreateWorkspacePage"))
22+
const TerminalPage = lazy(() => import("./pages/TerminalPage/TerminalPage"))
23+
const WorkspacesPage = lazy(() => import("./pages/WorkspacesPage/WorkspacesPage"))
24+
const CreateWorkspacePage = lazy(() => import("./pages/CreateWorkspacePage/CreateWorkspacePage"))
2525

26-
export const AppRouter: React.FC = () => (
27-
<React.Suspense fallback={<></>}>
26+
export const AppRouter: FC = () => (
27+
<Suspense fallback={<></>}>
2828
<Routes>
2929
<Route path="/">
3030
<Route
@@ -159,5 +159,5 @@ export const AppRouter: React.FC = () => (
159159
<Route path="*" element={<NotFoundPage />} />
160160
</Route>
161161
</Routes>
162-
</React.Suspense>
162+
</Suspense>
163163
)

site/src/Main.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { inspect } from "@xstate/inspect"
2-
import React from "react"
32
import ReactDOM from "react-dom"
43
import { Interpreter } from "xstate"
54
import { App } from "./app"

site/src/__mocks__/react-markdown.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React from "react"
1+
import { FC } from "react"
22

3-
const ReactMarkdown: React.FC = ({ children }) => {
3+
const ReactMarkdown: FC = ({ children }) => {
44
return <div data-testid="markdown">{children}</div>
55
}
66

site/src/app.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import CssBaseline from "@material-ui/core/CssBaseline"
22
import ThemeProvider from "@material-ui/styles/ThemeProvider"
3-
import React from "react"
3+
import { FC } from "react"
44
import { BrowserRouter as Router } from "react-router-dom"
55
import { SWRConfig } from "swr"
66
import { AppRouter } from "./AppRouter"
@@ -10,7 +10,7 @@ import { dark } from "./theme"
1010
import "./theme/globalFonts"
1111
import { XServiceProvider } from "./xServices/StateContext"
1212

13-
export const App: React.FC = () => {
13+
export const App: FC = () => {
1414
return (
1515
<Router>
1616
<SWRConfig

site/src/components/AuthAndFrame/AuthAndFrame.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react"
1+
import { FC } from "react"
22
import { Footer } from "../Footer/Footer"
33
import { Navbar } from "../Navbar/Navbar"
44
import { RequireAuth } from "../RequireAuth/RequireAuth"
@@ -10,7 +10,7 @@ interface AuthAndFrameProps {
1010
/**
1111
* Wraps page in RequireAuth and renders it between Navbar and Footer
1212
*/
13-
export const AuthAndFrame: React.FC<AuthAndFrameProps> = ({ children }) => (
13+
export const AuthAndFrame: FC<AuthAndFrameProps> = ({ children }) => (
1414
<RequireAuth>
1515
<>
1616
<Navbar />

site/src/components/AvatarData/AvatarData.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Story } from "@storybook/react"
2-
import React from "react"
32
import { AvatarData, AvatarDataProps } from "./AvatarData"
43

54
export default {

site/src/components/AvatarData/AvatarData.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Avatar from "@material-ui/core/Avatar"
22
import Link from "@material-ui/core/Link"
33
import { makeStyles } from "@material-ui/core/styles"
4-
import React from "react"
4+
import { FC } from "react"
55
import { Link as RouterLink } from "react-router-dom"
66
import { combineClasses } from "../../util/combineClasses"
77
import { firstLetter } from "../../util/firstLetter"
@@ -12,7 +12,7 @@ export interface AvatarDataProps {
1212
link?: string
1313
}
1414

15-
export const AvatarData: React.FC<AvatarDataProps> = ({ title, subtitle, link }) => {
15+
export const AvatarData: FC<AvatarDataProps> = ({ title, subtitle, link }) => {
1616
const styles = useStyles()
1717

1818
return (

site/src/components/BorderedMenu/BorderedMenu.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Story } from "@storybook/react"
2-
import React from "react"
32
import { BorderedMenuRow } from "../BorderedMenuRow/BorderedMenuRow"
43
import { BuildingIcon } from "../Icons/BuildingIcon"
54
import { UsersOutlinedIcon } from "../Icons/UsersOutlinedIcon"

site/src/components/BorderedMenu/BorderedMenu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Popover, { PopoverProps } from "@material-ui/core/Popover"
22
import { fade, makeStyles } from "@material-ui/core/styles"
3-
import React from "react"
3+
import { FC } from "react"
44

55
type BorderedMenuVariant = "admin-dropdown" | "user-dropdown"
66

77
export type BorderedMenuProps = Omit<PopoverProps, "variant"> & {
88
variant?: BorderedMenuVariant
99
}
1010

11-
export const BorderedMenu: React.FC<BorderedMenuProps> = ({ children, variant, ...rest }) => {
11+
export const BorderedMenu: FC<BorderedMenuProps> = ({ children, variant, ...rest }) => {
1212
const styles = useStyles()
1313

1414
return (

site/src/components/BorderedMenuRow/BorderedMenuRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import ListItem from "@material-ui/core/ListItem"
22
import { makeStyles } from "@material-ui/core/styles"
33
import SvgIcon from "@material-ui/core/SvgIcon"
44
import CheckIcon from "@material-ui/icons/Check"
5-
import React from "react"
5+
import { FC } from "react"
66
import { NavLink } from "react-router-dom"
77
import { ellipsizeText } from "../../util/ellipsizeText"
88
import { Typography } from "../Typography/Typography"
@@ -26,7 +26,7 @@ interface BorderedMenuRowProps {
2626
onClick?: () => void
2727
}
2828

29-
export const BorderedMenuRow: React.FC<BorderedMenuRowProps> = ({
29+
export const BorderedMenuRow: FC<BorderedMenuRowProps> = ({
3030
active,
3131
description,
3232
Icon,

site/src/components/BuildsTable/BuildsTable.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ComponentMeta, Story } from "@storybook/react"
2-
import React from "react"
32
import { MockBuilds } from "../../testHelpers/entities"
43
import { BuildsTable, BuildsTableProps } from "./BuildsTable"
54

site/src/components/BuildsTable/BuildsTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import TableCell from "@material-ui/core/TableCell"
66
import TableHead from "@material-ui/core/TableHead"
77
import TableRow from "@material-ui/core/TableRow"
88
import useTheme from "@material-ui/styles/useTheme"
9-
import React from "react"
9+
import { FC } from "react"
1010
import { useNavigate } from "react-router-dom"
1111
import * as TypesGen from "../../api/typesGenerated"
1212
import { displayWorkspaceBuildDuration, getDisplayStatus } from "../../util/workspace"
@@ -27,7 +27,7 @@ export interface BuildsTableProps {
2727
className?: string
2828
}
2929

30-
export const BuildsTable: React.FC<BuildsTableProps> = ({ builds, className }) => {
30+
export const BuildsTable: FC<BuildsTableProps> = ({ builds, className }) => {
3131
const isLoading = !builds
3232
const theme: Theme = useTheme()
3333
const navigate = useNavigate()

site/src/components/CliAuthToken/CliAuthToken.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Story } from "@storybook/react"
2-
import React from "react"
32
import { CliAuthToken, CliAuthTokenProps } from "./CliAuthToken"
43

54
export default {

site/src/components/CliAuthToken/CliAuthToken.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { screen } from "@testing-library/react"
2-
import React from "react"
32
import { render } from "../../testHelpers/renderHelpers"
43
import { CliAuthToken } from "./CliAuthToken"
54

site/src/components/CliAuthToken/CliAuthToken.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Paper from "@material-ui/core/Paper"
22
import { makeStyles } from "@material-ui/core/styles"
33
import Typography from "@material-ui/core/Typography"
4-
import React from "react"
4+
import { FC } from "react"
55
import { CodeExample } from "../CodeExample/CodeExample"
66

77
export interface CliAuthTokenProps {
88
sessionToken: string
99
}
1010

11-
export const CliAuthToken: React.FC<CliAuthTokenProps> = ({ sessionToken }) => {
11+
export const CliAuthToken: FC<CliAuthTokenProps> = ({ sessionToken }) => {
1212
const styles = useStyles()
1313
return (
1414
<Paper className={styles.container}>

site/src/components/CodeBlock/CodeBlock.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Story } from "@storybook/react"
2-
import React from "react"
32
import { CodeBlock, CodeBlockProps } from "./CodeBlock"
43

54
const sampleLines = `Successfully assigned coder/image-jcws7 to cluster-1

site/src/components/CodeBlock/CodeBlock.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { screen } from "@testing-library/react"
2-
import React from "react"
32
import { render } from "../../testHelpers/renderHelpers"
43
import { CodeBlock } from "./CodeBlock"
54

site/src/components/CodeBlock/CodeBlock.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { makeStyles } from "@material-ui/core/styles"
2-
import React from "react"
2+
import { FC, Fragment, ReactElement } from "react"
33
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
44
import { combineClasses } from "../../util/combineClasses"
55

66
export interface CodeBlockProps {
77
lines: string[]
8-
ctas?: React.ReactElement[]
8+
ctas?: ReactElement[]
99
className?: string
1010
}
1111

12-
export const CodeBlock: React.FC<CodeBlockProps> = ({ lines, ctas, className = "" }) => {
12+
export const CodeBlock: FC<CodeBlockProps> = ({ lines, ctas, className = "" }) => {
1313
const styles = useStyles()
1414

1515
return (
@@ -24,7 +24,7 @@ export const CodeBlock: React.FC<CodeBlockProps> = ({ lines, ctas, className = "
2424
{ctas && ctas.length && (
2525
<div className={styles.ctaBar}>
2626
{ctas.map((cta, i) => {
27-
return <React.Fragment key={i}>{cta}</React.Fragment>
27+
return <Fragment key={i}>{cta}</Fragment>
2828
})}
2929
</div>
3030
)}

site/src/components/CodeExample/CodeExample.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Story } from "@storybook/react"
2-
import React from "react"
32
import { CodeExample, CodeExampleProps } from "./CodeExample"
43

54
const sampleCode = `echo "Hello, world"`

site/src/components/CodeExample/CodeExample.test.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { screen } from "@testing-library/react"
2-
import React from "react"
32
import { render } from "../../testHelpers/renderHelpers"
43
import { CodeExample } from "./CodeExample"
54

site/src/components/CodeExample/CodeExample.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { makeStyles } from "@material-ui/core/styles"
2-
import React from "react"
2+
import { FC } from "react"
33
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
44
import { CopyButton } from "../CopyButton/CopyButton"
55

@@ -10,7 +10,7 @@ export interface CodeExampleProps {
1010
/**
1111
* Component to show single-line code examples, with a copy button
1212
*/
13-
export const CodeExample: React.FC<CodeExampleProps> = ({ code }) => {
13+
export const CodeExample: FC<CodeExampleProps> = ({ code }) => {
1414
const styles = useStyles()
1515

1616
return (

site/src/components/ConfirmDialog/ConfirmDialog.stories.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ComponentMeta, Story } from "@storybook/react"
2-
import React from "react"
32
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
43

54
export default {

0 commit comments

Comments
 (0)