mirror of
https://github.com/dstotijn/hetty.git
synced 2025-07-01 18:47:29 -04:00
Clear all HTTP request logs (#49)
* Create mutation to clear request logs * Add UI for clearing all HTTP request logs * Use consistent naming * Explicitly delete only from http_requests * Check if datebase is open * Add confirmation dialog
This commit is contained in:
53
admin/src/components/reqlog/ConfirmationDialog.tsx
Normal file
53
admin/src/components/reqlog/ConfirmationDialog.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
|
import Dialog from "@material-ui/core/Dialog";
|
||||||
|
import DialogActions from "@material-ui/core/DialogActions";
|
||||||
|
import DialogContent from "@material-ui/core/DialogContent";
|
||||||
|
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||||
|
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||||
|
|
||||||
|
export function useConfirmationDialog() {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const close = () => setIsOpen(false);
|
||||||
|
const open = () => setIsOpen(true);
|
||||||
|
|
||||||
|
return { open, close, isOpen };
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConfirmationDialog {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onConfirm: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConfirmationDialog(props: ConfirmationDialog) {
|
||||||
|
const { onClose, onConfirm, isOpen, children } = props;
|
||||||
|
|
||||||
|
function confirm() {
|
||||||
|
onConfirm();
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">Are you sure?</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
{children}
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onClose}>Abort</Button>
|
||||||
|
<Button onClick={confirm} autoFocus>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
@ -1,41 +1,24 @@
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { gql, useQuery } from "@apollo/client";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Typography,
|
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
Link as MaterialLink,
|
Link as MaterialLink,
|
||||||
|
Typography,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import Alert from "@material-ui/lab/Alert";
|
import Alert from "@material-ui/lab/Alert";
|
||||||
|
|
||||||
import RequestList from "./RequestList";
|
import RequestList from "./RequestList";
|
||||||
import LogDetail from "./LogDetail";
|
import LogDetail from "./LogDetail";
|
||||||
import CenteredPaper from "../CenteredPaper";
|
import CenteredPaper from "../CenteredPaper";
|
||||||
|
import { useHttpRequestLogs } from "./hooks/useHttpRequestLogs";
|
||||||
const HTTP_REQUEST_LOGS = gql`
|
|
||||||
query HttpRequestLogs {
|
|
||||||
httpRequestLogs {
|
|
||||||
id
|
|
||||||
method
|
|
||||||
url
|
|
||||||
timestamp
|
|
||||||
response {
|
|
||||||
statusCode
|
|
||||||
statusReason
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
function LogsOverview(): JSX.Element {
|
function LogsOverview(): JSX.Element {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const detailReqLogId =
|
const detailReqLogId =
|
||||||
router.query.id && parseInt(router.query.id as string, 10);
|
router.query.id && parseInt(router.query.id as string, 10);
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(HTTP_REQUEST_LOGS, {
|
const { loading, error, data } = useHttpRequestLogs();
|
||||||
pollInterval: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleLogClick = (reqId: number) => {
|
const handleLogClick = (reqId: number) => {
|
||||||
router.push("/proxy/logs?id=" + reqId, undefined, {
|
router.push("/proxy/logs?id=" + reqId, undefined, {
|
||||||
|
@ -16,10 +16,16 @@ import {
|
|||||||
import IconButton from "@material-ui/core/IconButton";
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
import SearchIcon from "@material-ui/icons/Search";
|
import SearchIcon from "@material-ui/icons/Search";
|
||||||
import FilterListIcon from "@material-ui/icons/FilterList";
|
import FilterListIcon from "@material-ui/icons/FilterList";
|
||||||
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
import React, { useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { gql, useApolloClient, useMutation, useQuery } from "@apollo/client";
|
import { gql, useMutation, useQuery } from "@apollo/client";
|
||||||
import { withoutTypename } from "../../lib/omitTypename";
|
import { withoutTypename } from "../../lib/omitTypename";
|
||||||
import { Alert } from "@material-ui/lab";
|
import { Alert } from "@material-ui/lab";
|
||||||
|
import { useClearHTTPRequestLog } from "./hooks/useClearHTTPRequestLog";
|
||||||
|
import {
|
||||||
|
ConfirmationDialog,
|
||||||
|
useConfirmationDialog,
|
||||||
|
} from "./ConfirmationDialog";
|
||||||
|
|
||||||
const FILTER = gql`
|
const FILTER = gql`
|
||||||
query HttpRequestLogFilter {
|
query HttpRequestLogFilter {
|
||||||
@ -79,15 +85,14 @@ function Search(): JSX.Element {
|
|||||||
FILTER
|
FILTER
|
||||||
);
|
);
|
||||||
|
|
||||||
const client = useApolloClient();
|
|
||||||
const [
|
const [
|
||||||
setFilterMutate,
|
setFilterMutate,
|
||||||
{ error: setFilterErr, loading: setFilterLoading },
|
{ error: setFilterErr, loading: setFilterLoading },
|
||||||
] = useMutation<{
|
] = useMutation<{
|
||||||
setHttpRequestLogFilter: SearchFilter | null;
|
setHttpRequestLogFilter: SearchFilter | null;
|
||||||
}>(SET_FILTER, {
|
}>(SET_FILTER, {
|
||||||
update(_, { data: { setHttpRequestLogFilter } }) {
|
update(cache, { data: { setHttpRequestLogFilter } }) {
|
||||||
client.writeQuery({
|
cache.writeQuery({
|
||||||
query: FILTER,
|
query: FILTER,
|
||||||
data: {
|
data: {
|
||||||
httpRequestLogFilter: setHttpRequestLogFilter,
|
httpRequestLogFilter: setHttpRequestLogFilter,
|
||||||
@ -96,6 +101,12 @@ function Search(): JSX.Element {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [
|
||||||
|
clearHTTPRequestLog,
|
||||||
|
clearHTTPRequestLogResult,
|
||||||
|
] = useClearHTTPRequestLog();
|
||||||
|
const clearHTTPConfirmationDialog = useConfirmationDialog();
|
||||||
|
|
||||||
const filterRef = useRef<HTMLElement | null>();
|
const filterRef = useRef<HTMLElement | null>();
|
||||||
const [filterOpen, setFilterOpen] = useState(false);
|
const [filterOpen, setFilterOpen] = useState(false);
|
||||||
|
|
||||||
@ -111,90 +122,112 @@ function Search(): JSX.Element {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ClickAwayListener onClickAway={handleClickAway}>
|
<Box>
|
||||||
<Box style={{ display: "inline-block" }}>
|
<Error prefix="Error fetching filter" error={filterErr} />
|
||||||
{filterErr && (
|
<Error prefix="Error setting filter" error={setFilterErr} />
|
||||||
<Box mb={4}>
|
<Error
|
||||||
<Alert severity="error">
|
prefix="Error clearing all HTTP logs"
|
||||||
Error fetching filter: {filterErr.message}
|
error={clearHTTPRequestLogResult.error}
|
||||||
</Alert>
|
/>
|
||||||
</Box>
|
<Box style={{ display: "flex", flex: 1 }}>
|
||||||
)}
|
<ClickAwayListener onClickAway={handleClickAway}>
|
||||||
{setFilterErr && (
|
<Paper
|
||||||
<Box mb={4}>
|
component="form"
|
||||||
<Alert severity="error">
|
onSubmit={handleSubmit}
|
||||||
Error setting filter: {setFilterErr.message}
|
ref={filterRef}
|
||||||
</Alert>
|
className={classes.root}
|
||||||
</Box>
|
>
|
||||||
)}
|
<Tooltip title="Toggle filter options">
|
||||||
<Paper
|
<IconButton
|
||||||
component="form"
|
className={classes.iconButton}
|
||||||
onSubmit={handleSubmit}
|
onClick={() => setFilterOpen(!filterOpen)}
|
||||||
ref={filterRef}
|
style={{
|
||||||
className={classes.root}
|
color:
|
||||||
>
|
filter?.httpRequestLogFilter !== null
|
||||||
<Tooltip title="Toggle filter options">
|
? theme.palette.secondary.main
|
||||||
<IconButton
|
: "inherit",
|
||||||
className={classes.iconButton}
|
}}
|
||||||
onClick={() => setFilterOpen(!filterOpen)}
|
>
|
||||||
style={{
|
{filterLoading || setFilterLoading ? (
|
||||||
color:
|
<CircularProgress
|
||||||
filter?.httpRequestLogFilter !== null
|
className={classes.filterLoading}
|
||||||
? theme.palette.secondary.main
|
size={23}
|
||||||
: "inherit",
|
/>
|
||||||
}}
|
) : (
|
||||||
>
|
<FilterListIcon />
|
||||||
{filterLoading || setFilterLoading ? (
|
)}
|
||||||
<CircularProgress className={classes.filterLoading} size={23} />
|
</IconButton>
|
||||||
) : (
|
</Tooltip>
|
||||||
<FilterListIcon />
|
<InputBase
|
||||||
)}
|
className={classes.input}
|
||||||
</IconButton>
|
placeholder="Search proxy logs…"
|
||||||
</Tooltip>
|
onFocus={() => setFilterOpen(true)}
|
||||||
<InputBase
|
|
||||||
className={classes.input}
|
|
||||||
placeholder="Search proxy logs…"
|
|
||||||
onFocus={() => setFilterOpen(true)}
|
|
||||||
/>
|
|
||||||
<Tooltip title="Search">
|
|
||||||
<IconButton type="submit" className={classes.iconButton}>
|
|
||||||
<SearchIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</Paper>
|
|
||||||
|
|
||||||
<Popper
|
|
||||||
className={classes.filterPopper}
|
|
||||||
open={filterOpen}
|
|
||||||
anchorEl={filterRef.current}
|
|
||||||
placement="bottom-start"
|
|
||||||
>
|
|
||||||
<Paper className={classes.filterOptions}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={
|
|
||||||
filter?.httpRequestLogFilter?.onlyInScope ? true : false
|
|
||||||
}
|
|
||||||
disabled={filterLoading || setFilterLoading}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFilterMutate({
|
|
||||||
variables: {
|
|
||||||
filter: {
|
|
||||||
...withoutTypename(filter?.httpRequestLogFilter),
|
|
||||||
onlyInScope: e.target.checked,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="Only show in-scope requests"
|
|
||||||
/>
|
/>
|
||||||
|
<Tooltip title="Search">
|
||||||
|
<IconButton type="submit" className={classes.iconButton}>
|
||||||
|
<SearchIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Popper
|
||||||
|
className={classes.filterPopper}
|
||||||
|
open={filterOpen}
|
||||||
|
anchorEl={filterRef.current}
|
||||||
|
placement="bottom-start"
|
||||||
|
>
|
||||||
|
<Paper className={classes.filterOptions}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={
|
||||||
|
filter?.httpRequestLogFilter?.onlyInScope ? true : false
|
||||||
|
}
|
||||||
|
disabled={filterLoading || setFilterLoading}
|
||||||
|
onChange={(e) =>
|
||||||
|
setFilterMutate({
|
||||||
|
variables: {
|
||||||
|
filter: {
|
||||||
|
...withoutTypename(filter?.httpRequestLogFilter),
|
||||||
|
onlyInScope: e.target.checked,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Only show in-scope requests"
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
</Popper>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Popper>
|
</ClickAwayListener>
|
||||||
|
<Box style={{ marginLeft: "auto" }}>
|
||||||
|
<Tooltip title="Clear all">
|
||||||
|
<IconButton onClick={clearHTTPConfirmationDialog.open}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</ClickAwayListener>
|
<ConfirmationDialog
|
||||||
|
isOpen={clearHTTPConfirmationDialog.isOpen}
|
||||||
|
onClose={clearHTTPConfirmationDialog.close}
|
||||||
|
onConfirm={clearHTTPRequestLog}
|
||||||
|
>
|
||||||
|
All proxy logs are going to be removed. This action cannot be undone.
|
||||||
|
</ConfirmationDialog>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Error(props: { prefix: string; error?: Error }) {
|
||||||
|
if (!props.error) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box mb={4}>
|
||||||
|
<Alert severity="error">
|
||||||
|
{props.prefix}: {props.error.message}
|
||||||
|
</Alert>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
admin/src/components/reqlog/hooks/useClearHTTPRequestLog.ts
Normal file
16
admin/src/components/reqlog/hooks/useClearHTTPRequestLog.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { gql, useMutation } from "@apollo/client";
|
||||||
|
import { HTTP_REQUEST_LOGS } from "./useHttpRequestLogs";
|
||||||
|
|
||||||
|
const CLEAR_HTTP_REQUEST_LOG = gql`
|
||||||
|
mutation ClearHTTPRequestLog {
|
||||||
|
clearHTTPRequestLog {
|
||||||
|
success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function useClearHTTPRequestLog() {
|
||||||
|
return useMutation(CLEAR_HTTP_REQUEST_LOG, {
|
||||||
|
refetchQueries: [{ query: HTTP_REQUEST_LOGS }],
|
||||||
|
});
|
||||||
|
}
|
22
admin/src/components/reqlog/hooks/useHttpRequestLogs.ts
Normal file
22
admin/src/components/reqlog/hooks/useHttpRequestLogs.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { gql, useQuery } from "@apollo/client";
|
||||||
|
|
||||||
|
export const HTTP_REQUEST_LOGS = gql`
|
||||||
|
query HttpRequestLogs {
|
||||||
|
httpRequestLogs {
|
||||||
|
id
|
||||||
|
method
|
||||||
|
url
|
||||||
|
timestamp
|
||||||
|
response {
|
||||||
|
statusCode
|
||||||
|
statusReason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function useHttpRequestLogs() {
|
||||||
|
return useQuery(HTTP_REQUEST_LOGS, {
|
||||||
|
pollInterval: 1000,
|
||||||
|
});
|
||||||
|
}
|
@ -43,6 +43,10 @@ type DirectiveRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ComplexityRoot struct {
|
type ComplexityRoot struct {
|
||||||
|
ClearHTTPRequestLogResult struct {
|
||||||
|
Success func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
CloseProjectResult struct {
|
CloseProjectResult struct {
|
||||||
Success func(childComplexity int) int
|
Success func(childComplexity int) int
|
||||||
}
|
}
|
||||||
@ -81,6 +85,7 @@ type ComplexityRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mutation struct {
|
Mutation struct {
|
||||||
|
ClearHTTPRequestLog func(childComplexity int) int
|
||||||
CloseProject func(childComplexity int) int
|
CloseProject func(childComplexity int) int
|
||||||
DeleteProject func(childComplexity int, name string) int
|
DeleteProject func(childComplexity int, name string) int
|
||||||
OpenProject func(childComplexity int, name string) int
|
OpenProject func(childComplexity int, name string) int
|
||||||
@ -118,6 +123,7 @@ type MutationResolver interface {
|
|||||||
OpenProject(ctx context.Context, name string) (*Project, error)
|
OpenProject(ctx context.Context, name string) (*Project, error)
|
||||||
CloseProject(ctx context.Context) (*CloseProjectResult, error)
|
CloseProject(ctx context.Context) (*CloseProjectResult, error)
|
||||||
DeleteProject(ctx context.Context, name string) (*DeleteProjectResult, error)
|
DeleteProject(ctx context.Context, name string) (*DeleteProjectResult, error)
|
||||||
|
ClearHTTPRequestLog(ctx context.Context) (*ClearHTTPRequestLogResult, error)
|
||||||
SetScope(ctx context.Context, scope []ScopeRuleInput) ([]ScopeRule, error)
|
SetScope(ctx context.Context, scope []ScopeRuleInput) ([]ScopeRule, error)
|
||||||
SetHTTPRequestLogFilter(ctx context.Context, filter *HTTPRequestLogFilterInput) (*HTTPRequestLogFilter, error)
|
SetHTTPRequestLogFilter(ctx context.Context, filter *HTTPRequestLogFilterInput) (*HTTPRequestLogFilter, error)
|
||||||
}
|
}
|
||||||
@ -145,6 +151,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
_ = ec
|
_ = ec
|
||||||
switch typeName + "." + field {
|
switch typeName + "." + field {
|
||||||
|
|
||||||
|
case "ClearHTTPRequestLogResult.success":
|
||||||
|
if e.complexity.ClearHTTPRequestLogResult.Success == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.ClearHTTPRequestLogResult.Success(childComplexity), true
|
||||||
|
|
||||||
case "CloseProjectResult.success":
|
case "CloseProjectResult.success":
|
||||||
if e.complexity.CloseProjectResult.Success == nil {
|
if e.complexity.CloseProjectResult.Success == nil {
|
||||||
break
|
break
|
||||||
@ -278,6 +291,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.HTTPResponseLog.StatusReason(childComplexity), true
|
return e.complexity.HTTPResponseLog.StatusReason(childComplexity), true
|
||||||
|
|
||||||
|
case "Mutation.clearHTTPRequestLog":
|
||||||
|
if e.complexity.Mutation.ClearHTTPRequestLog == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.ClearHTTPRequestLog(childComplexity), true
|
||||||
|
|
||||||
case "Mutation.closeProject":
|
case "Mutation.closeProject":
|
||||||
if e.complexity.Mutation.CloseProject == nil {
|
if e.complexity.Mutation.CloseProject == nil {
|
||||||
break
|
break
|
||||||
@ -553,6 +573,10 @@ type DeleteProjectResult {
|
|||||||
success: Boolean!
|
success: Boolean!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClearHTTPRequestLogResult {
|
||||||
|
success: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
input HttpRequestLogFilterInput {
|
input HttpRequestLogFilterInput {
|
||||||
onlyInScope: Boolean
|
onlyInScope: Boolean
|
||||||
}
|
}
|
||||||
@ -574,6 +598,7 @@ type Mutation {
|
|||||||
openProject(name: String!): Project
|
openProject(name: String!): Project
|
||||||
closeProject: CloseProjectResult!
|
closeProject: CloseProjectResult!
|
||||||
deleteProject(name: String!): DeleteProjectResult!
|
deleteProject(name: String!): DeleteProjectResult!
|
||||||
|
clearHTTPRequestLog: ClearHTTPRequestLogResult!
|
||||||
setScope(scope: [ScopeRuleInput!]!): [ScopeRule!]!
|
setScope(scope: [ScopeRuleInput!]!): [ScopeRule!]!
|
||||||
setHttpRequestLogFilter(
|
setHttpRequestLogFilter(
|
||||||
filter: HttpRequestLogFilterInput
|
filter: HttpRequestLogFilterInput
|
||||||
@ -730,6 +755,41 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg
|
|||||||
|
|
||||||
// region **************************** field.gotpl *****************************
|
// region **************************** field.gotpl *****************************
|
||||||
|
|
||||||
|
func (ec *executionContext) _ClearHTTPRequestLogResult_success(ctx context.Context, field graphql.CollectedField, obj *ClearHTTPRequestLogResult) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "ClearHTTPRequestLogResult",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return obj.Success, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(bool)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _CloseProjectResult_success(ctx context.Context, field graphql.CollectedField, obj *CloseProjectResult) (ret graphql.Marshaler) {
|
func (ec *executionContext) _CloseProjectResult_success(ctx context.Context, field graphql.CollectedField, obj *CloseProjectResult) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -1502,6 +1562,41 @@ func (ec *executionContext) _Mutation_deleteProject(ctx context.Context, field g
|
|||||||
return ec.marshalNDeleteProjectResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐDeleteProjectResult(ctx, field.Selections, res)
|
return ec.marshalNDeleteProjectResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐDeleteProjectResult(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_clearHTTPRequestLog(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
fc := &graphql.FieldContext{
|
||||||
|
Object: "Mutation",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: true,
|
||||||
|
IsResolver: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return ec.resolvers.Mutation().ClearHTTPRequestLog(rctx)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, fc) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*ClearHTTPRequestLogResult)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNClearHTTPRequestLogResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐClearHTTPRequestLogResult(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_setScope(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Mutation_setScope(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -3271,6 +3366,33 @@ func (ec *executionContext) unmarshalInputScopeRuleInput(ctx context.Context, ob
|
|||||||
|
|
||||||
// region **************************** object.gotpl ****************************
|
// region **************************** object.gotpl ****************************
|
||||||
|
|
||||||
|
var clearHTTPRequestLogResultImplementors = []string{"ClearHTTPRequestLogResult"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _ClearHTTPRequestLogResult(ctx context.Context, sel ast.SelectionSet, obj *ClearHTTPRequestLogResult) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, clearHTTPRequestLogResultImplementors)
|
||||||
|
|
||||||
|
out := graphql.NewFieldSet(fields)
|
||||||
|
var invalids uint32
|
||||||
|
for i, field := range fields {
|
||||||
|
switch field.Name {
|
||||||
|
case "__typename":
|
||||||
|
out.Values[i] = graphql.MarshalString("ClearHTTPRequestLogResult")
|
||||||
|
case "success":
|
||||||
|
out.Values[i] = ec._ClearHTTPRequestLogResult_success(ctx, field, obj)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.Dispatch()
|
||||||
|
if invalids > 0 {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
var closeProjectResultImplementors = []string{"CloseProjectResult"}
|
var closeProjectResultImplementors = []string{"CloseProjectResult"}
|
||||||
|
|
||||||
func (ec *executionContext) _CloseProjectResult(ctx context.Context, sel ast.SelectionSet, obj *CloseProjectResult) graphql.Marshaler {
|
func (ec *executionContext) _CloseProjectResult(ctx context.Context, sel ast.SelectionSet, obj *CloseProjectResult) graphql.Marshaler {
|
||||||
@ -3516,6 +3638,11 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
invalids++
|
invalids++
|
||||||
}
|
}
|
||||||
|
case "clearHTTPRequestLog":
|
||||||
|
out.Values[i] = ec._Mutation_clearHTTPRequestLog(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "setScope":
|
case "setScope":
|
||||||
out.Values[i] = ec._Mutation_setScope(ctx, field)
|
out.Values[i] = ec._Mutation_setScope(ctx, field)
|
||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
@ -3985,6 +4112,20 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNClearHTTPRequestLogResult2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐClearHTTPRequestLogResult(ctx context.Context, sel ast.SelectionSet, v ClearHTTPRequestLogResult) graphql.Marshaler {
|
||||||
|
return ec._ClearHTTPRequestLogResult(ctx, sel, &v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNClearHTTPRequestLogResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐClearHTTPRequestLogResult(ctx context.Context, sel ast.SelectionSet, v *ClearHTTPRequestLogResult) graphql.Marshaler {
|
||||||
|
if v == nil {
|
||||||
|
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
return ec._ClearHTTPRequestLogResult(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) marshalNCloseProjectResult2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐCloseProjectResult(ctx context.Context, sel ast.SelectionSet, v CloseProjectResult) graphql.Marshaler {
|
func (ec *executionContext) marshalNCloseProjectResult2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐCloseProjectResult(ctx context.Context, sel ast.SelectionSet, v CloseProjectResult) graphql.Marshaler {
|
||||||
return ec._CloseProjectResult(ctx, sel, &v)
|
return ec._CloseProjectResult(ctx, sel, &v)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ClearHTTPRequestLogResult struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
}
|
||||||
|
|
||||||
type CloseProjectResult struct {
|
type CloseProjectResult struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,13 @@ func (r *mutationResolver) DeleteProject(ctx context.Context, name string) (*Del
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) ClearHTTPRequestLog(ctx context.Context) (*ClearHTTPRequestLogResult, error) {
|
||||||
|
if err := r.RequestLogService.ClearRequests(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("could not clear request log: %v", err)
|
||||||
|
}
|
||||||
|
return &ClearHTTPRequestLogResult{true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) SetScope(ctx context.Context, input []ScopeRuleInput) ([]ScopeRule, error) {
|
func (r *mutationResolver) SetScope(ctx context.Context, input []ScopeRuleInput) ([]ScopeRule, error) {
|
||||||
rules := make([]scope.Rule, len(input))
|
rules := make([]scope.Rule, len(input))
|
||||||
for i, rule := range input {
|
for i, rule := range input {
|
||||||
|
@ -58,6 +58,10 @@ type DeleteProjectResult {
|
|||||||
success: Boolean!
|
success: Boolean!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClearHTTPRequestLogResult {
|
||||||
|
success: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
input HttpRequestLogFilterInput {
|
input HttpRequestLogFilterInput {
|
||||||
onlyInScope: Boolean
|
onlyInScope: Boolean
|
||||||
}
|
}
|
||||||
@ -79,6 +83,7 @@ type Mutation {
|
|||||||
openProject(name: String!): Project
|
openProject(name: String!): Project
|
||||||
closeProject: CloseProjectResult!
|
closeProject: CloseProjectResult!
|
||||||
deleteProject(name: String!): DeleteProjectResult!
|
deleteProject(name: String!): DeleteProjectResult!
|
||||||
|
clearHTTPRequestLog: ClearHTTPRequestLogResult!
|
||||||
setScope(scope: [ScopeRuleInput!]!): [ScopeRule!]!
|
setScope(scope: [ScopeRuleInput!]!): [ScopeRule!]!
|
||||||
setHttpRequestLogFilter(
|
setHttpRequestLogFilter(
|
||||||
filter: HttpRequestLogFilterInput
|
filter: HttpRequestLogFilterInput
|
||||||
|
@ -215,6 +215,17 @@ var headerFieldToColumnMap = map[string]string{
|
|||||||
"value": "value",
|
"value": "value",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) ClearRequestLogs(ctx context.Context) error {
|
||||||
|
if c.db == nil {
|
||||||
|
return proj.ErrNoProject
|
||||||
|
}
|
||||||
|
_, err := c.db.Exec("DELETE FROM http_requests")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sqlite: could not delete requests: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) FindRequestLogs(
|
func (c *Client) FindRequestLogs(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
filter reqlog.FindRequestsFilter,
|
filter reqlog.FindRequestsFilter,
|
||||||
|
@ -17,6 +17,7 @@ type Repository interface {
|
|||||||
FindRequestLogByID(ctx context.Context, id int64) (Request, error)
|
FindRequestLogByID(ctx context.Context, id int64) (Request, error)
|
||||||
AddRequestLog(ctx context.Context, req http.Request, body []byte, timestamp time.Time) (*Request, error)
|
AddRequestLog(ctx context.Context, req http.Request, body []byte, timestamp time.Time) (*Request, error)
|
||||||
AddResponseLog(ctx context.Context, reqID int64, res http.Response, body []byte, timestamp time.Time) (*Response, error)
|
AddResponseLog(ctx context.Context, reqID int64, res http.Response, body []byte, timestamp time.Time) (*Response, error)
|
||||||
|
ClearRequestLogs(ctx context.Context) error
|
||||||
UpsertSettings(ctx context.Context, module string, settings interface{}) error
|
UpsertSettings(ctx context.Context, module string, settings interface{}) error
|
||||||
FindSettingsByModule(ctx context.Context, module string, settings interface{}) error
|
FindSettingsByModule(ctx context.Context, module string, settings interface{}) error
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,10 @@ func (svc *Service) SetRequestLogFilter(ctx context.Context, filter FindRequests
|
|||||||
return svc.repo.UpsertSettings(ctx, "reqlog", svc)
|
return svc.repo.UpsertSettings(ctx, "reqlog", svc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *Service) ClearRequests(ctx context.Context) error {
|
||||||
|
return svc.repo.ClearRequestLogs(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (svc *Service) addRequest(
|
func (svc *Service) addRequest(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req http.Request,
|
req http.Request,
|
||||||
|
Reference in New Issue
Block a user