mirror of
https://github.com/wassname/talk.git
synced 2026-07-15 11:26:58 +08:00
[CORL 133] API Review (#2197)
* refactor: removed unused subscription code
* refactor: removed management api's
* refactor: cleanup of connections
* refactor: refactored comments edge
* refactor: simplified connection resolving
* feat: added story connection edge
* fix: added story index
* feat: added user pagination and user edge
* fix: added filter to comment query
* fix: removed unused resolvers
* fix: creating a comment reply should require auth
* refactor: cleanup of graph files
* feat: removed display name, made username non-unique
* fix: fixed tests
* fix: fixed tests
* fix: added more api docs
* fix: fixed bug with installer
* refactor: fixes and updates
* fix: added linting for graphql, fixed schema
* feat: added docker build tests
* fix: upped output timeout
* fix: fixed stacktraces in production builds
* fix: removed `git add`
- `git add` was causing issues with
partial staged changs on files
* feat: improved error messaging for auth
* refactor: cleaned up queue names
* fix: merge error
This commit is contained in:
@@ -9,7 +9,7 @@ export default function getQueueConnection(
|
||||
const root = store.getRoot();
|
||||
if (queue === "rejected") {
|
||||
return ConnectionHandler.getConnection(root, "RejectedQueue_comments", {
|
||||
filter: { status: "REJECTED" },
|
||||
status: "REJECTED",
|
||||
});
|
||||
}
|
||||
const queuesRecord = root.getLinkedRecord("moderationQueues")!;
|
||||
|
||||
@@ -3,13 +3,11 @@ import React, { StatelessComponent } from "react";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { HorizontalGutter } from "talk-ui/components";
|
||||
|
||||
import DisplayNamesConfigContainer from "../containers/DisplayNamesConfigContainer";
|
||||
import AuthIntegrationsConfig from "./AuthIntegrationsConfig";
|
||||
|
||||
interface Props {
|
||||
disabled?: boolean;
|
||||
auth: PropTypesOf<typeof AuthIntegrationsConfig>["auth"] &
|
||||
PropTypesOf<typeof DisplayNamesConfigContainer>["auth"];
|
||||
auth: PropTypesOf<typeof AuthIntegrationsConfig>["auth"];
|
||||
onInitValues: (values: any) => void;
|
||||
}
|
||||
|
||||
@@ -19,11 +17,6 @@ const AuthConfig: StatelessComponent<Props> = ({
|
||||
onInitValues,
|
||||
}) => (
|
||||
<HorizontalGutter size="double" data-testid="configure-authContainer">
|
||||
<DisplayNamesConfigContainer
|
||||
disabled={disabled}
|
||||
auth={auth}
|
||||
onInitValues={onInitValues}
|
||||
/>
|
||||
<AuthIntegrationsConfig
|
||||
disabled={disabled}
|
||||
auth={auth}
|
||||
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { StatelessComponent } from "react";
|
||||
import { Field } from "react-final-form";
|
||||
|
||||
import { parseStringBool } from "talk-framework/lib/form";
|
||||
import {
|
||||
Flex,
|
||||
FormField,
|
||||
HorizontalGutter,
|
||||
RadioButton,
|
||||
Typography,
|
||||
} from "talk-ui/components";
|
||||
|
||||
import Header from "../../../components/Header";
|
||||
|
||||
interface Props {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const DisplayNamesConfig: StatelessComponent<Props> = ({ disabled }) => (
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<Localized id="configure-auth-displayNamesConfig-title">
|
||||
<Header>Display Names</Header>
|
||||
</Localized>
|
||||
<Localized id="configure-auth-displayNamesConfig-explanationShort">
|
||||
<Typography variant="detail">
|
||||
Some AUTH integrations include a Display Name as well as a User Name.
|
||||
</Typography>
|
||||
</Localized>
|
||||
<Localized id="configure-auth-displayNamesConfig-explanationLong">
|
||||
<Typography variant="detail">
|
||||
A User Name has to be unique (there can only be one Juan_Doe, for
|
||||
example), whereas a Display Name does not. If your AUTH provider allows
|
||||
for Display Names, you can enable this option. This allows for fewer
|
||||
strange names (Juan_Doe23245) – however it could also be used to
|
||||
spoof/impersonate another user.
|
||||
</Typography>
|
||||
</Localized>
|
||||
|
||||
<FormField>
|
||||
<Flex direction="row" itemGutter="double">
|
||||
<Field
|
||||
name={"auth.displayName.enabled"}
|
||||
type="radio"
|
||||
parse={parseStringBool}
|
||||
value
|
||||
>
|
||||
{({ input }) => (
|
||||
<Localized id="configure-auth-displayNamesConfig-showDisplayNames">
|
||||
<RadioButton
|
||||
id={`${input.name}-true`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
Show Display Names (if available)
|
||||
</RadioButton>
|
||||
</Localized>
|
||||
)}
|
||||
</Field>
|
||||
<Field
|
||||
name={"auth.displayName.enabled"}
|
||||
type="radio"
|
||||
parse={parseStringBool}
|
||||
value={false}
|
||||
>
|
||||
{({ input }) => (
|
||||
<Localized id="configure-auth-displayNamesConfig-hideDisplayNames">
|
||||
<RadioButton
|
||||
id={`${input.name}-false`}
|
||||
name={input.name}
|
||||
onChange={input.onChange}
|
||||
onFocus={input.onFocus}
|
||||
onBlur={input.onBlur}
|
||||
checked={input.checked}
|
||||
disabled={disabled}
|
||||
value={input.value}
|
||||
>
|
||||
Hide Display Names (if available)
|
||||
</RadioButton>
|
||||
</Localized>
|
||||
)}
|
||||
</Field>
|
||||
</Flex>
|
||||
</FormField>
|
||||
</HorizontalGutter>
|
||||
);
|
||||
|
||||
export default DisplayNamesConfig;
|
||||
-1
@@ -104,7 +104,6 @@ const enhanced = withFragmentContainer<Props>({
|
||||
...SSOConfigContainer_auth
|
||||
...SSOConfigContainer_authReadOnly
|
||||
...LocalAuthConfigContainer_auth
|
||||
...DisplayNamesConfigContainer_auth
|
||||
...OIDCConfigContainer_auth
|
||||
...OIDCConfigContainer_authReadOnly
|
||||
}
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import React from "react";
|
||||
import { graphql } from "react-relay";
|
||||
|
||||
import { DisplayNamesConfigContainer_auth as AuthData } from "talk-admin/__generated__/DisplayNamesConfigContainer_auth.graphql";
|
||||
import { withFragmentContainer } from "talk-framework/lib/relay";
|
||||
|
||||
import DisplayNamesConfig from "../components/DisplayNamesConfig";
|
||||
|
||||
interface Props {
|
||||
auth: AuthData;
|
||||
onInitValues: (values: AuthData) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
class DisplayNamesConfigContainer extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
props.onInitValues(props.auth);
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { disabled } = this.props;
|
||||
return <DisplayNamesConfig disabled={disabled} />;
|
||||
}
|
||||
}
|
||||
|
||||
const enhanced = withFragmentContainer<Props>({
|
||||
auth: graphql`
|
||||
fragment DisplayNamesConfigContainer_auth on Auth {
|
||||
displayName {
|
||||
enabled
|
||||
}
|
||||
}
|
||||
`,
|
||||
})(DisplayNamesConfigContainer);
|
||||
|
||||
export default enhanced;
|
||||
+2
-2
@@ -36,8 +36,8 @@ const CreateUsername: StatelessComponent<CreateUsernameForm> = props => {
|
||||
<HorizontalGutter size="oneAndAHalf">
|
||||
<Localized id="createUsername-whatItIs">
|
||||
<Typography variant="bodyCopy">
|
||||
Your username is a unique identifier that will appear on all
|
||||
of your comments.
|
||||
Your username is an identifier that will appear on all of your
|
||||
comments.
|
||||
</Typography>
|
||||
</Localized>
|
||||
{submitError && (
|
||||
|
||||
@@ -79,7 +79,7 @@ const enhanced = (withPaginationContainer<
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
) {
|
||||
comments(filter: { status: REJECTED }, first: $count, after: $cursor)
|
||||
comments(status: REJECTED, first: $count, after: $cursor)
|
||||
@connection(key: "RejectedQueue_comments") {
|
||||
edges {
|
||||
node {
|
||||
|
||||
@@ -11,7 +11,7 @@ exports[`accepts valid username 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
@@ -69,7 +69,7 @@ exports[`checks for invalid username 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
@@ -169,7 +169,7 @@ exports[`renders createUsername view 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
@@ -232,7 +232,7 @@ exports[`shows error when submitting empty form 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
@@ -303,7 +303,7 @@ exports[`shows server error 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="CallOut-root CallOut-colorError CallOut-fullWidth"
|
||||
@@ -373,7 +373,7 @@ exports[`successfully sets username 1`] = `
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Your username is a unique identifier that will appear on all of your comments.
|
||||
Your username is an identifier that will appear on all of your comments.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
|
||||
@@ -79,7 +79,7 @@ it("sign out when clicking on sign in as", async () => {
|
||||
const restMock = sinon.mock(context.rest);
|
||||
restMock
|
||||
.expects("fetch")
|
||||
.withArgs("/tenant/auth", {
|
||||
.withArgs("/auth", {
|
||||
method: "DELETE",
|
||||
})
|
||||
.once()
|
||||
|
||||
@@ -99,7 +99,7 @@ it("shows server error", async () => {
|
||||
const restMock = sinon.mock(context.rest);
|
||||
restMock
|
||||
.expects("fetch")
|
||||
.withArgs("/tenant/auth/local", {
|
||||
.withArgs("/auth/local", {
|
||||
method: "POST",
|
||||
body: {
|
||||
email: "hans@test.com",
|
||||
@@ -133,7 +133,7 @@ it("submits form successfully", async () => {
|
||||
const restMock = sinon.mock(context.rest);
|
||||
restMock
|
||||
.expects("fetch")
|
||||
.withArgs("/tenant/auth/local", {
|
||||
.withArgs("/auth/local", {
|
||||
method: "POST",
|
||||
body: {
|
||||
email: "hans@test.com",
|
||||
|
||||
@@ -40,7 +40,7 @@ it("logs out", async () => {
|
||||
const restMock = sinon.mock(context.rest);
|
||||
restMock
|
||||
.expects("fetch")
|
||||
.withArgs("/tenant/auth", {
|
||||
.withArgs("/auth", {
|
||||
method: "DELETE",
|
||||
})
|
||||
.once()
|
||||
|
||||
@@ -1853,80 +1853,6 @@ exports[`renders configure auth 1`] = `
|
||||
className="HorizontalGutter-root HorizontalGutter-double"
|
||||
data-testid="configure-authContainer"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-oneAndAHalf"
|
||||
>
|
||||
<h1
|
||||
className="Typography-root Typography-heading1 Typography-colorTextPrimary Header-root"
|
||||
>
|
||||
Display Names
|
||||
</h1>
|
||||
<p
|
||||
className="Typography-root Typography-detail Typography-colorTextPrimary"
|
||||
>
|
||||
Some Authentication Integrations include a Display Name as well as a User Name.
|
||||
</p>
|
||||
<p
|
||||
className="Typography-root Typography-detail Typography-colorTextPrimary"
|
||||
>
|
||||
A User Name has to be unique (there can only be one Juan_Doe, for example),
|
||||
whereas a Display Name does not. If your authentication provider allows for Display Names,
|
||||
you can enable this option. This allows for fewer strange names (Juan_Doe23245) –
|
||||
however it could also be used to spoof/impersonate another user.
|
||||
</p>
|
||||
<div
|
||||
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-doubleItemGutter Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="Flex-root RadioButton-root Flex-flex Flex-alignCenter"
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="auth.displayName.enabled-true"
|
||||
name="auth.displayName.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="auth.displayName.enabled-true"
|
||||
>
|
||||
Show Display Names (if available)
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root RadioButton-root Flex-flex Flex-alignCenter"
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="auth.displayName.enabled-false"
|
||||
name="auth.displayName.enabled"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="auth.displayName.enabled-false"
|
||||
>
|
||||
Hide Display Names (if available)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-double"
|
||||
>
|
||||
|
||||
@@ -35,9 +35,6 @@ export const settings = {
|
||||
},
|
||||
},
|
||||
auth: {
|
||||
displayName: {
|
||||
enabled: false,
|
||||
},
|
||||
integrations: {
|
||||
local: {
|
||||
enabled: true,
|
||||
@@ -100,9 +97,6 @@ export const settingsWithEmptyAuth = {
|
||||
...settings,
|
||||
id: "settings",
|
||||
auth: {
|
||||
displayName: {
|
||||
enabled: false,
|
||||
},
|
||||
integrations: {
|
||||
local: {
|
||||
enabled: true,
|
||||
|
||||
@@ -357,7 +357,7 @@ describe("rejected queue", () => {
|
||||
const testRenderer = await createTestRenderer({
|
||||
Query: {
|
||||
comments: sinon.stub().callsFake((_, data) => {
|
||||
expect(data).toEqual({ first: 5, filter: { status: "REJECTED" } });
|
||||
expect(data).toEqual({ first: 5, status: "REJECTED" });
|
||||
return {
|
||||
edges: [
|
||||
{
|
||||
@@ -390,7 +390,7 @@ describe("rejected queue", () => {
|
||||
s.onFirstCall().callsFake((_, data) => {
|
||||
expect(data).toEqual({
|
||||
first: 5,
|
||||
filter: { status: "REJECTED" },
|
||||
status: "REJECTED",
|
||||
});
|
||||
return {
|
||||
edges: [
|
||||
@@ -414,7 +414,7 @@ describe("rejected queue", () => {
|
||||
expect(data).toEqual({
|
||||
first: 10,
|
||||
after: rejectedComments[1].createdAt,
|
||||
filter: { status: "REJECTED" },
|
||||
status: "REJECTED",
|
||||
});
|
||||
return {
|
||||
edges: [
|
||||
@@ -490,7 +490,7 @@ describe("rejected queue", () => {
|
||||
const testRenderer = await createTestRenderer({
|
||||
Query: {
|
||||
comments: sinon.stub().callsFake((_, data) => {
|
||||
expect(data).toEqual({ first: 5, filter: { status: "REJECTED" } });
|
||||
expect(data).toEqual({ first: 5, status: "REJECTED" });
|
||||
return {
|
||||
edges: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user