Skip to content

Commit 428f70d

Browse files
committed
Merge branch 'master' into issue-1182-cache-update
2 parents a79a6cc + 9a6fa7f commit 428f70d

File tree

8 files changed

+172
-43
lines changed

8 files changed

+172
-43
lines changed

console/src/components/Services/Data/Function/Modify/ModifyCustomFunction.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,21 @@ class ModifyCustomFunction extends React.Component {
3131
}
3232
componentDidMount() {
3333
const { functionName, schema } = this.props.params;
34-
if (!functionName) {
34+
if (!functionName || !schema) {
3535
this.props.dispatch(push(prefixUrl));
3636
}
3737
Promise.all([
3838
this.props.dispatch(fetchCustomFunction(functionName, schema)),
3939
]);
4040
}
41+
componentWillReceiveProps(nextProps) {
42+
const { functionName, schema } = this.props.params;
43+
if (functionName !== nextProps.params.functionName || schema !== nextProps.params.schema) {
44+
Promise.all([
45+
this.props.dispatch(fetchCustomFunction(nextProps.params.functionName, nextProps.params.schema)),
46+
]);
47+
}
48+
}
4149
loadRunSQLAndLoadPage() {
4250
const { functionDefinition } = this.props.functions;
4351
Promise.all([

console/src/components/Services/Data/Function/Permission/Permission.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22

33
import Helmet from 'react-helmet';
44
import CommonTabLayout from '../../../Layout/CommonTabLayout/CommonTabLayout';
5-
import { Link } from 'react-router';
5+
// import { Link } from 'react-router';
66
import { push } from 'react-router-redux';
77

88
import { pageTitle, appPrefix } from '../Modify/constants';
@@ -16,21 +16,25 @@ import { fetchCustomFunction } from '../customFunctionReducer';
1616

1717
class Permission extends React.Component {
1818
componentDidMount() {
19-
const { functionName } = this.props.params;
19+
const { functionName, schema } = this.props.params;
2020
if (!functionName) {
2121
this.props.dispatch(push(prefixUrl));
2222
}
23-
Promise.all([this.props.dispatch(fetchCustomFunction(functionName))]);
23+
Promise.all([
24+
this.props.dispatch(fetchCustomFunction(functionName, schema)),
25+
]);
2426
}
2527
render() {
2628
const styles = require('../Modify/ModifyCustomFunction.scss');
2729
const {
2830
functionSchema: schema,
2931
functionName,
3032
setOffTable,
33+
setOffTableSchema,
3134
} = this.props.functions;
35+
3236
const baseUrl = `${appPrefix}/schema/${schema}/functions/${functionName}`;
33-
const permissionTableUrl = `${appPrefix}/schema/${schema}/tables/${setOffTable}/permissions`;
37+
const permissionTableUrl = `${prefixUrl}/schema/${setOffTableSchema}/tables/${setOffTable}/permissions`;
3438

3539
const breadCrumbs = [
3640
{
@@ -78,14 +82,14 @@ class Permission extends React.Component {
7882
applicable to the data returned by this function
7983
</p>
8084
<div className={styles.commonBtn}>
81-
<Link to={permissionTableUrl}>
85+
<a href={permissionTableUrl}>
8286
<button
8387
className={styles.yellow_button}
8488
data-test={'custom-function-permission-btn'}
8589
>
8690
{`${setOffTable} Permissions`}
8791
</button>
88-
</Link>
92+
</a>
8993
</div>
9094
</div>
9195
);

console/src/components/Services/Data/Function/customFunctionReducer.js

+26-13
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,25 @@ const fetchCustomFunction = (functionName, schema) => {
170170
const deleteFunctionSql = () => {
171171
return (dispatch, getState) => {
172172
const currentSchema = getState().tables.currentSchema;
173-
const functionName = getState().functions.functionName;
174-
const functionDefinition = getState().functions.functionDefinition;
175-
const sqlDropFunction =
176-
'DROP FUNCTION ' +
177-
'"' +
178-
currentSchema +
179-
'"' +
180-
'.' +
181-
'"' +
182-
functionName +
183-
'"';
173+
const {
174+
functionName,
175+
functionDefinition,
176+
inputArgTypes,
177+
} = getState().functions;
178+
let functionWSchemaName =
179+
'"' + currentSchema + '"' + '.' + '"' + functionName + '"';
180+
181+
if (inputArgTypes.length > 0) {
182+
let functionString = '(';
183+
inputArgTypes.forEach((i, index) => {
184+
functionString +=
185+
i + ' ' + (index === inputArgTypes.length - 1 ? ')' : ',');
186+
});
187+
functionWSchemaName += functionString;
188+
}
189+
190+
const sqlDropFunction = 'DROP FUNCTION ' + functionWSchemaName;
191+
184192
const sqlUpQueries = [
185193
{
186194
type: 'run_sql',
@@ -203,9 +211,11 @@ const deleteFunctionSql = () => {
203211
const errorMsg = 'Deleting function failed';
204212

205213
const customOnSuccess = () => {
206-
dispatch(_push('/'));
214+
dispatch(_push(`/schema/${currentSchema}`));
215+
};
216+
const customOnError = () => {
217+
dispatch({ type: DELETE_CUSTOM_FUNCTION_FAIL });
207218
};
208-
const customOnError = () => {};
209219

210220
dispatch({ type: DELETING_CUSTOM_FUNCTION });
211221
return dispatch(
@@ -318,6 +328,9 @@ const customFunctionReducer = (state = functionData, action) => {
318328
functionSchema: action.data[0][0].function_schema || null,
319329
functionDefinition: action.data[1][0].function_definition || null,
320330
setOffTable: action.data[1][0].return_type_name || null,
331+
setOffTableSchema: action.data[1][0].return_type_schema || null,
332+
inputArgNames: action.data[1][0].input_arg_names || null,
333+
inputArgTypes: action.data[1][0].input_arg_types || null,
321334
isFetching: false,
322335
isFetchError: null,
323336
};

console/src/components/Services/Data/Function/customFunctionState.js

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const functionData = {
1212
functionSchema: '',
1313
functionDefinition: '',
1414
setOffTable: '',
15+
setOffTableSchema: '',
16+
inputArgNames: [],
17+
inputArgTypes: [],
1518
...asyncState,
1619
};
1720

install-manifests/README.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ Various installation / deployment methods for Hasura GraphQL Engine
44

55
1. [Docker Compose](docker-compose)
66
2. [Docker Compose with HTTPS using Caddy](docker-compose-https)
7-
3. [Docker run](docker-run)
8-
3. [Kubernetes](kubernetes)
9-
7+
3. [Docker Compose with PostGIS enabled Postgres](docker-compose-postgis)
8+
4. [Docker Compose with pgAdmin](docker-compose-pgadmin)
9+
5. [Docker run](docker-run)
10+
6. [Kubernetes](kubernetes)
11+
7. [Azure Container Instance without Postgres](azure-container)
12+
8. [Azure Container Instances with Postgres](azure-container-with-pg)
1013

1114
## License
1215

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Hasura GraphQL Engine on Docker with pgAdmin
2+
3+
This Docker Compose setup runs [Hasura GraphQL Engine](https://github.com/hasura/graphql-engine) along with Postgres and [pgAdmin4](https://www.pgadmin.org/) using `docker-compose`.
4+
5+
## Pre-requisites
6+
7+
- [Docker](https://docs.docker.com/install/)
8+
- [Docker Compose](https://docs.docker.com/compose/install/)
9+
10+
## Usage
11+
12+
- Clone this repo on a machine where you'd like to deploy graphql engine
13+
- Edit `docker-compose.yaml` and change `PGADMIN_DEFAULT_EMAIL` and `PGADMIN_DEFAULT_PASSWORD` to something secure (default pgAdmin login email/password) default value for above variables are:
14+
- **PGADMIN_DEFAULT_EMAIL:** `[email protected]`
15+
- **PGADMIN_DEFAULT_PASSWORD:** `admin`
16+
- Read more `Environment Variables` here: https://hub.docker.com/r/dpage/pgadmin4/
17+
- Edit `docker-compose.yaml` and change `HASURA_GRAPHQL_ACCESS_KEY` to something secure
18+
- `docker-compose up -d`
19+
- Navigate to `http://localhost:5050`, login and add a new server with the following parameters:
20+
General - Name: Hasura
21+
Connection - Host: `hasura`
22+
Username: `postgres`
23+
Password: leave empty
24+
25+
## Important endpoints
26+
27+
- GraphQL endpoint will be `http://localhost:8080/v1alpha1/graphql`
28+
- Hasura Console will be available on `http://localhost:8080/console`
29+
- pgAdmin will be available on `http://localhost:5050`
30+
31+
32+
## Connecting to External Postgres
33+
34+
If you want to connect to an external/existing postgres database, replace `HASURA_GRAPHQL_DATABASE_URL` in `docker-compose.yaml` with your database url.
35+
36+
**Note: localhost will resolve to the container ip inside a docker container, not the host ip**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
version: '3.6'
2+
services:
3+
postgres:
4+
image: postgres
5+
restart: always
6+
volumes:
7+
- db_data:/var/lib/postgresql/data
8+
pgadmin:
9+
image: dpage/pgadmin4
10+
restart: always
11+
depends_on:
12+
- postgres
13+
ports:
14+
- 5050:80
15+
## you can change pgAdmin default username/password with below environment variables
16+
environment:
17+
PGADMIN_DEFAULT_EMAIL: [email protected]
18+
PGADMIN_DEFAULT_PASSWORD: admin
19+
graphql-engine:
20+
image: hasura/graphql-engine:v1.0.0-alpha37
21+
ports:
22+
- "8080:8080"
23+
depends_on:
24+
- "postgres"
25+
restart: always
26+
environment:
27+
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:@postgres:5432/postgres
28+
HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
29+
## uncomment next line to set an access key
30+
# HASURA_GRAPHQL_ACCESS_KEY: mysecretaccesskey
31+
volumes:
32+
db_data:

server/src-lib/Hasura/Events/Lib.hs

+50-20
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ data TriggerMeta
6565

6666
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''TriggerMeta)
6767

68+
data DeliveryInfo
69+
= DeliveryInfo
70+
{ diCurrentRetry :: Int
71+
, diMaxRetries :: Int
72+
} deriving (Show, Eq)
73+
74+
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''DeliveryInfo)
75+
6876
data Event
6977
= Event
7078
{ eId :: EventId
@@ -75,18 +83,29 @@ data Event
7583
, eCreatedAt :: Time.UTCTime
7684
} deriving (Show, Eq)
7785

78-
instance ToJSON Event where
79-
toJSON (Event eid (QualifiedObject sn tn) trigger event _ created)=
80-
object [ "id" .= eid
81-
, "table" .= object [ "schema" .= sn
82-
, "name" .= tn
83-
]
84-
, "trigger" .= trigger
85-
, "event" .= event
86-
, "created_at" .= created
86+
$(deriveFromJSON (aesonDrop 1 snakeCase){omitNothingFields=True} ''Event)
87+
88+
newtype QualifiedTableStrict = QualifiedTableStrict
89+
{ getQualifiedTable :: QualifiedTable
90+
} deriving (Show, Eq)
91+
92+
instance ToJSON QualifiedTableStrict where
93+
toJSON (QualifiedTableStrict (QualifiedObject sn tn)) =
94+
object [ "schema" .= sn
95+
, "name" .= tn
8796
]
8897

89-
$(deriveFromJSON (aesonDrop 1 snakeCase){omitNothingFields=True} ''Event)
98+
data EventPayload
99+
= EventPayload
100+
{ epId :: EventId
101+
, epTable :: QualifiedTableStrict
102+
, epTrigger :: TriggerMeta
103+
, epEvent :: Value
104+
, epDeliveryInfo :: DeliveryInfo
105+
, epCreatedAt :: Time.UTCTime
106+
} deriving (Show, Eq)
107+
108+
$(deriveToJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''EventPayload)
90109

91110
data WebhookRequest
92111
= WebhookRequest
@@ -266,6 +285,17 @@ tryWebhook logenv pool e = do
266285
eventId = eId e
267286
headerInfos = etiHeaders eti
268287
headers = map encodeHeader headerInfos
288+
eventPayload = EventPayload
289+
{ epId = eId e
290+
, epTable = QualifiedTableStrict { getQualifiedTable = eTable e}
291+
, epTrigger = eTrigger e
292+
, epEvent = eEvent e
293+
, epDeliveryInfo = DeliveryInfo
294+
{ diCurrentRetry = eTries e
295+
, diMaxRetries = rcNumRetries $ etiRetryConf eti
296+
}
297+
, epCreatedAt = eCreatedAt e
298+
}
269299
eeCtx <- asks getter
270300
-- wait for counter and then increment beforing making http
271301
liftIO $ atomically $ do
@@ -276,7 +306,7 @@ tryWebhook logenv pool e = do
276306
else modifyTVar' c (+1)
277307
let options = addHeaders headers W.defaults
278308
decodedHeaders = map (decodeHeader headerInfos) $ options CL.^. W.headers
279-
eitherResp <- runExceptT $ runHTTP options (mkAnyHTTPPost (T.unpack webhook) (Just $ toJSON e)) (Just (ExtraContext createdAt eventId))
309+
eitherResp <- runExceptT $ runHTTP options (mkAnyHTTPPost (T.unpack webhook) (Just $ toJSON eventPayload)) (Just (ExtraContext createdAt eventId))
280310

281311
--decrement counter once http is done
282312
liftIO $ atomically $ do
@@ -287,32 +317,32 @@ tryWebhook logenv pool e = do
287317
Left err ->
288318
case err of
289319
HClient excp -> let errMsg = TBS.fromLBS $ encode $ show excp
290-
in runFailureQ pool $ mkInvo e 1000 decodedHeaders errMsg []
320+
in runFailureQ pool $ mkInvo eventPayload 1000 decodedHeaders errMsg []
291321
HParse _ detail -> let errMsg = TBS.fromLBS $ encode detail
292-
in runFailureQ pool $ mkInvo e 1001 decodedHeaders errMsg []
322+
in runFailureQ pool $ mkInvo eventPayload 1001 decodedHeaders errMsg []
293323
HStatus errResp -> let respPayload = hrsBody errResp
294324
respHeaders = hrsHeaders errResp
295325
respStatus = hrsStatus errResp
296-
in runFailureQ pool $ mkInvo e respStatus decodedHeaders respPayload respHeaders
326+
in runFailureQ pool $ mkInvo eventPayload respStatus decodedHeaders respPayload respHeaders
297327
HOther detail -> let errMsg = (TBS.fromLBS $ encode detail)
298-
in runFailureQ pool $ mkInvo e 500 decodedHeaders errMsg []
328+
in runFailureQ pool $ mkInvo eventPayload 500 decodedHeaders errMsg []
299329
Right resp -> let respPayload = hrsBody resp
300330
respHeaders = hrsHeaders resp
301331
respStatus = hrsStatus resp
302-
in runSuccessQ pool e $ mkInvo e respStatus decodedHeaders respPayload respHeaders
332+
in runSuccessQ pool e $ mkInvo eventPayload respStatus decodedHeaders respPayload respHeaders
303333
case finally of
304334
Left err -> liftIO $ logger $ L.toEngineLog $ EventInternalErr err
305335
Right _ -> return ()
306336
return eitherResp
307337
where
308-
mkInvo :: Event -> Int -> [HeaderConf] -> TBS.TByteString -> [HeaderConf] -> Invocation
309-
mkInvo e' status reqHeaders respBody respHeaders
338+
mkInvo :: EventPayload -> Int -> [HeaderConf] -> TBS.TByteString -> [HeaderConf] -> Invocation
339+
mkInvo ep status reqHeaders respBody respHeaders
310340
= let resp = if isInitError status then mkErr respBody else mkResp status respBody respHeaders
311341
in
312342
Invocation
313-
(eId e')
343+
(epId ep)
314344
status
315-
(mkWebhookReq (toJSON e) reqHeaders)
345+
(mkWebhookReq (toJSON ep) reqHeaders)
316346
resp
317347
addHeaders :: [(N.HeaderName, BS.ByteString)] -> W.Options -> W.Options
318348
addHeaders headers opts = foldl (\acc h -> acc CL.& W.header (fst h) CL..~ [snd h] ) opts headers

0 commit comments

Comments
 (0)