├── README.md ├── components ├── api │ ├── .gitignore │ ├── .ballerina │ │ └── .gitignore │ ├── Ballerina.toml │ ├── build-dev.sh │ ├── db │ │ └── client.bal │ ├── idp │ │ ├── client.bal │ │ ├── validator.bal │ │ └── user_info_retriver.bal │ ├── docker_registry │ │ ├── docker_auth_client.bal │ │ ├── registry_client.bal │ │ ├── auth_token.bal │ │ └── registry.bal │ ├── core │ │ └── response_handler.bal │ ├── validator │ │ └── configReader.bal │ ├── constants │ │ └── constants.bal │ └── gen │ │ └── schema.bal ├── portal │ ├── .eslintignore │ ├── src │ │ ├── img │ │ │ ├── .eslintrc.json │ │ │ ├── CreateOrg.jpg │ │ │ ├── SearchImages.png │ │ │ ├── SearchOrgs.png │ │ │ ├── celleryCmd.png │ │ │ ├── celleryError.jpg │ │ │ ├── celleryOverview.jpg │ │ │ ├── celleryOverviewBg.png │ │ │ ├── CellImage.js │ │ │ └── celleryLogo.svg │ │ ├── components │ │ │ ├── App.test.js │ │ │ ├── appLayout │ │ │ │ ├── index.js │ │ │ │ ├── ButtonAppBarCollapse.js │ │ │ │ ├── Header.js │ │ │ │ └── Footer.js │ │ │ ├── sdk │ │ │ │ ├── appLayout │ │ │ │ │ └── index.js │ │ │ │ ├── SignInFailure.js │ │ │ │ ├── SignInSuccess.js │ │ │ │ └── index.js │ │ │ ├── explore │ │ │ │ └── index.js │ │ │ ├── common │ │ │ │ ├── error │ │ │ │ │ ├── ErrorBoundary.js │ │ │ │ │ ├── UnknownError.js │ │ │ │ │ ├── NotFound.js │ │ │ │ │ └── SignInRequired.js │ │ │ │ ├── Description.js │ │ │ │ ├── CustomizedTabs.js │ │ │ │ └── state │ │ │ │ │ └── index.js │ │ │ ├── SignIn.js │ │ │ ├── org │ │ │ │ ├── OrgDeleteDialog.js │ │ │ │ └── MemberList.js │ │ │ └── image │ │ │ │ ├── ImageDeleteDialog.js │ │ │ │ └── version │ │ │ │ └── VersionDeleteDialog.js │ │ ├── index.css │ │ ├── index.js │ │ └── utils │ │ │ ├── api │ │ │ ├── dataUtils.js │ │ │ └── authUtils.test.js │ │ │ ├── constants.js │ │ │ └── common │ │ │ └── notificationUtils.js │ ├── public │ │ ├── favicon.ico │ │ ├── manifest.json │ │ ├── icons │ │ │ ├── cell.svg │ │ │ ├── focusedCell.svg │ │ │ ├── composite.svg │ │ │ ├── focusedComposite.svg │ │ │ ├── gateway.svg │ │ │ └── component.svg │ │ └── index.html │ ├── node-server │ │ ├── package.json │ │ ├── config │ │ │ └── portal.json │ │ └── serve.js │ └── package.json ├── proxy │ ├── .ballerina │ │ └── .gitignore │ ├── Ballerina.toml │ ├── build-dev.sh │ ├── database │ │ ├── client.bal │ │ ├── lock.bal │ │ └── queries.bal │ └── docker_registry │ │ └── registry.bal ├── docker-auth │ ├── pkg │ │ ├── extension │ │ │ ├── logger.go │ │ │ ├── execIDGenerator.go │ │ │ └── constants.go │ │ ├── auth │ │ │ └── authz_handler.go │ │ └── db │ │ │ └── connection.go │ ├── go.mod │ ├── test │ │ ├── data.sql │ │ └── init.sql │ └── cmd │ │ ├── authz │ │ └── authorization.go │ │ └── authn │ │ └── authentication.go └── identity-server-customization │ └── cellery-identity-customizations │ └── src │ └── main │ └── java │ └── io │ └── cellery │ └── hub │ └── identity │ └── extension │ ├── internal │ └── CelleryCustomizationDataHolder.java │ └── DBPersistanceManager.java ├── .codecov.yml ├── docker ├── identity-server │ ├── resources │ │ └── authenticationendpoint │ │ │ ├── images │ │ │ ├── favicon.png │ │ │ ├── cellery-error.jpg │ │ │ └── logo-inverse.svg │ │ │ └── cellery_error.jsp │ └── Dockerfile ├── portal │ └── Dockerfile ├── docker-auth │ ├── docker-auth-base │ │ └── Dockerfile │ └── Dockerfile ├── api │ └── Dockerfile └── proxy │ └── Dockerfile ├── .travis.yml ├── .gitignore ├── issue_template.md └── pull_request_template.md /README.md: -------------------------------------------------------------------------------- 1 | # cellery-hub -------------------------------------------------------------------------------- /components/api/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /components/api/.ballerina/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /components/portal/.eslintignore: -------------------------------------------------------------------------------- 1 | src/serviceWorker.js 2 | -------------------------------------------------------------------------------- /components/proxy/.ballerina/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /components/api/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | org-name = "cellery_hub_api" 3 | version = "0.1.0" 4 | -------------------------------------------------------------------------------- /components/proxy/Ballerina.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | org-name = "cellery_hub" 3 | version = "0.1.0" 4 | -------------------------------------------------------------------------------- /components/portal/src/img/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "max-len": "off" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /components/portal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/public/favicon.ico -------------------------------------------------------------------------------- /components/portal/src/img/CreateOrg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/CreateOrg.jpg -------------------------------------------------------------------------------- /components/portal/src/img/SearchImages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/SearchImages.png -------------------------------------------------------------------------------- /components/portal/src/img/SearchOrgs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/SearchOrgs.png -------------------------------------------------------------------------------- /components/portal/src/img/celleryCmd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/celleryCmd.png -------------------------------------------------------------------------------- /components/portal/src/img/celleryError.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/celleryError.jpg -------------------------------------------------------------------------------- /components/portal/src/img/celleryOverview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/celleryOverview.jpg -------------------------------------------------------------------------------- /components/portal/src/img/celleryOverviewBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/components/portal/src/img/celleryOverviewBg.png -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 80..95 3 | round: down 4 | precision: 2 5 | status: 6 | project: yes 7 | patch: yes 8 | changes: yes 9 | -------------------------------------------------------------------------------- /docker/identity-server/resources/authenticationendpoint/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/docker/identity-server/resources/authenticationendpoint/images/favicon.png -------------------------------------------------------------------------------- /docker/identity-server/resources/authenticationendpoint/images/cellery-error.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wso2/cellery-hub/master/docker/identity-server/resources/authenticationendpoint/images/cellery-error.jpg -------------------------------------------------------------------------------- /components/portal/node-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wso2-cellery/hub-portal-server", 3 | "version": "0.1.0", 4 | "description": "Cellery Hub Portal - Server", 5 | "main": "serve.js", 6 | "author": "WSO2 Org", 7 | "license": "Apache-2.0", 8 | "dependencies": { 9 | "express": "^4.16.4", 10 | "express-history-api-fallback": "^2.2.1" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /components/portal/node-server/config/portal.json: -------------------------------------------------------------------------------- 1 | { 2 | "hubPublicUrl": "https://hub.cellery.io", 3 | "hubApiUrl": "https://api.hub.cellery.io/api/0.1.0", 4 | "reCaptchaSiteKey": "fillme", 5 | "idp": { 6 | "url": "https://idp.hub.cellery.io", 7 | "hubClientId": "celleryhubapplication", 8 | "sdkClientId": "cellerycliapplication" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /components/portal/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Cellery Hub", 3 | "name": "Cellery Hub", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /components/portal/public/icons/cell.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /components/portal/public/icons/focusedCell.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /components/portal/public/icons/composite.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: java 3 | go: 4 | - 1.11.x 5 | jdk: 6 | - openjdk8 7 | node_js: 8 | - 9.11.2 9 | services: 10 | - docker 11 | cache: 12 | directories: 13 | - .autoconf 14 | - $HOME/.m2 15 | before_install: 16 | - npm i -g npm 17 | - mkdir -p $HOME/gopath/src/github.com/cellery-io 18 | - mv ${TRAVIS_BUILD_DIR} $GOPATH/src/github.com/cellery-io/cellery-hub 19 | - export TRAVIS_BUILD_DIR=$HOME/gopath/src/github.com/cellery-io/cellery-hub 20 | - cd $HOME/gopath/src/github.com/cellery-io/cellery-hub 21 | script: 22 | - travis_wait 30 make clean init check-style build test docker 23 | after_success: 24 | - bash <(curl -s https://codecov.io/bash) 25 | -------------------------------------------------------------------------------- /components/portal/public/icons/focusedComposite.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # Idea files 26 | .idea/ 27 | *.iml 28 | *.iws 29 | *.ipr 30 | 31 | # Maven 32 | **/target/* 33 | 34 | # NPM 35 | **/node_modules/* 36 | **/dist/* 37 | **/build/* 38 | **/coverage/* 39 | 40 | # OS 41 | .DS_Store 42 | 43 | # Cellery Hub 44 | deployment/mysql/mnt 45 | deployment/docker-registry/mnt 46 | deployment/docker-auth/extension-logs 47 | docker/deployment-init/files/idp-variables.sh 48 | 49 | coverage.txt 50 | -------------------------------------------------------------------------------- /components/api/build-dev.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # ------------------------------------------------------------------------ 3 | # 4 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License 17 | # 18 | # ------------------------------------------------------------------------ 19 | 20 | ballerina build --experimental 21 | -------------------------------------------------------------------------------- /components/proxy/build-dev.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # ------------------------------------------------------------------------ 3 | # 4 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License 17 | # 18 | # ------------------------------------------------------------------------ 19 | 20 | ballerina build --experimental 21 | -------------------------------------------------------------------------------- /issue_template.md: -------------------------------------------------------------------------------- 1 | **Description:** 2 | 3 | 4 | **Suggested Labels:** 5 | 6 | 7 | **Suggested Assignees:** 8 | 9 | 10 | **Affected Product Version:** 11 | 12 | **OS, DB, other environment details and versions:** 13 | 14 | **Steps to reproduce:** 15 | 16 | 17 | **Related Issues:** 18 | -------------------------------------------------------------------------------- /components/portal/public/icons/gateway.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /components/portal/src/img/CellImage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import SvgIcon from "@material-ui/core/SvgIcon"; 3 | 4 | const CellImage = (props) => ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ); 13 | 14 | export default CellImage; 15 | -------------------------------------------------------------------------------- /components/portal/src/components/App.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import App from "./App"; 20 | import React from "react"; 21 | import ReactDOM from "react-dom"; 22 | 23 | it("renders without crashing", () => { 24 | const div = document.createElement("div"); 25 | ReactDOM.render(, div); 26 | ReactDOM.unmountComponentAtNode(div); 27 | }); 28 | 29 | -------------------------------------------------------------------------------- /components/portal/public/icons/component.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | μ 11 | ' 12 | 13 | -------------------------------------------------------------------------------- /docker/portal/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM node:11.2.0-slim 20 | LABEL MAINTAINER="WSO2 Cellery Maintainers " 21 | 22 | ARG PORTAL_PORT=3000 23 | ARG APP_DIR=/portal 24 | 25 | WORKDIR ${APP_DIR} 26 | 27 | COPY ./target/ ${APP_DIR}/ 28 | 29 | ENV PORTAL_PORT=${PORTAL_PORT} 30 | 31 | EXPOSE ${PORTAL_PORT} 32 | 33 | RUN npm ci 34 | 35 | ENTRYPOINT ["node", "serve.js"] 36 | -------------------------------------------------------------------------------- /components/docker-auth/pkg/extension/logger.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package extension 20 | 21 | import ( 22 | "go.uber.org/zap" 23 | ) 24 | 25 | func NewLogger() *zap.SugaredLogger { 26 | config := zap.NewDevelopmentConfig() 27 | config.OutputPaths = []string{"stdout"} 28 | config.DisableStacktrace = true 29 | logger, err := config.Build() 30 | if err != nil { 31 | zap.NewExample().Sugar().Errorf("Error while creating the logger: %s", err) 32 | return nil 33 | } 34 | return logger.Sugar() 35 | } 36 | -------------------------------------------------------------------------------- /components/docker-auth/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cellery-io/cellery-hub/components/docker-auth 2 | 3 | go 1.12 4 | 5 | require ( 6 | cloud.google.com/go v0.44.3 7 | github.com/cesanta/docker_auth/auth_server v0.0.0-20190831165929-82573a5f102c 8 | github.com/cesanta/glog v0.0.0-20150527111657-22eb27a0ae19 9 | github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 10 | github.com/deckarep/golang-set v1.7.1 11 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 12 | github.com/docker/distribution v2.7.1+incompatible 13 | github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 14 | github.com/facebookgo/httpdown v0.0.0-20180706035922-5979d39b15c2 15 | github.com/go-ldap/ldap v3.0.3+incompatible 16 | github.com/go-sql-driver/mysql v1.4.1 17 | github.com/schwarmco/go-cartesian-product v0.0.0-20180515110546-d5ee747a6dc9 18 | github.com/syndtr/goleveldb v1.0.0 19 | go.uber.org/atomic v1.4.0 // indirect 20 | go.uber.org/multierr v1.1.0 // indirect 21 | go.uber.org/zap v1.10.0 22 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 23 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 24 | google.golang.org/api v0.9.0 25 | gopkg.in/fsnotify.v1 v1.4.7 26 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 27 | gopkg.in/yaml.v2 v2.2.2 28 | ) 29 | -------------------------------------------------------------------------------- /components/docker-auth/pkg/extension/execIDGenerator.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package extension 20 | 21 | import ( 22 | "crypto/rand" 23 | "fmt" 24 | 25 | "go.uber.org/zap" 26 | ) 27 | 28 | func GetExecID(logger *zap.SugaredLogger) (string, error) { 29 | b := make([]byte, 16) 30 | _, err := rand.Read(b) 31 | if err != nil { 32 | return "", fmt.Errorf("error generating uuid : %v", err) 33 | } 34 | uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) 35 | logger.Debugf("Exec ID : %s is generated", uuid) 36 | return uuid, nil 37 | } 38 | -------------------------------------------------------------------------------- /components/portal/src/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | padding: 0; 22 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 23 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 24 | sans-serif; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | background-color: #ffffff!important; 28 | height: 100vh; 29 | } 30 | 31 | code { 32 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; 33 | } 34 | -------------------------------------------------------------------------------- /components/portal/src/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import "./index.css"; 20 | import App from "./components/App"; 21 | import React from "react"; 22 | import ReactDOM from "react-dom"; 23 | import * as serviceWorker from "./serviceWorker"; 24 | 25 | ReactDOM.render(, document.getElementById("root")); 26 | 27 | /* 28 | * If you want your app to work offline and load faster, you can change 29 | * unregister() to register() below. Note this comes with some pitfalls. 30 | * Learn more about service workers: https://bit.ly/CRA-PWA 31 | */ 32 | serviceWorker.unregister(); 33 | -------------------------------------------------------------------------------- /docker/docker-auth/docker-auth-base/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM golang:1.12.9 20 | RUN mkdir -p /go/src/github.com/cesanta 21 | RUN cd /go/src/github.com && cd cesanta && git clone https://github.com/cesanta/docker_auth.git 22 | COPY ./target/docker_auth/ /go/src/github.com/cesanta/ 23 | RUN export GO111MODULE=on && cd /go/src/github.com/cesanta/docker_auth/auth_server && git checkout 82573a5f102c2d886428415bf6fcb8d94706834a && sed -i 's/Version/"1.0.0"/g' main.go && sed -i 's/BuildId/"1.0.0"/g' main.go && go build main.go 24 | -------------------------------------------------------------------------------- /components/api/db/client.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | import ballerina/config; 19 | 20 | mysql:Client connection = new ({ 21 | host: config:getAsString("database.host"), 22 | port: config:getAsInt("database.port"), 23 | name: config:getAsString("database.default"), 24 | username: config:getAsString("database.user"), 25 | password: config:getAsString("database.password"), 26 | dbOptions: { 27 | useSSL: true, 28 | allowPublicKeyRetrieval: true 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /components/proxy/database/client.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/config; 20 | import ballerina/mysql; 21 | 22 | mysql:Client celleryHubDB = new({ 23 | host: config:getAsString("database.host"), 24 | port: config:getAsInt("database.port"), 25 | name: config:getAsString("database.default"), 26 | username: config:getAsString("database.user"), 27 | password: config:getAsString("database.password"), 28 | dbOptions: { 29 | useSSL: true, 30 | allowPublicKeyRetrieval: true 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /components/portal/public/index.html: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Cellery Hub 28 | 29 | 30 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docker/api/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM ballerina/ballerina:0.991.0 as builder 20 | LABEL MAINTAINER="WSO2 Cellery Maintainers " 21 | 22 | ARG PROJECT_DIR="/workspace" 23 | WORKDIR ${PROJECT_DIR} 24 | USER root 25 | 26 | COPY ./target/ ./ 27 | 28 | RUN chown -R ballerina ${PROJECT_DIR} 29 | USER ballerina 30 | 31 | RUN ballerina build --experimental 32 | 33 | FROM ballerina/ballerina:0.991.0 34 | 35 | ARG WORK_DIR="/home/ballerina" 36 | WORKDIR ${WORK_DIR} 37 | USER ballerina 38 | 39 | COPY --from=builder /workspace/target/core.balx ./ 40 | 41 | RUN wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar -P ${BALLERINA_HOME}/bre/lib 42 | 43 | EXPOSE 9090 44 | 45 | ENTRYPOINT cp ${API_CONF} ./ballerina.conf && ballerina run core.balx 2>&1 | tee hub_api.log 46 | -------------------------------------------------------------------------------- /components/api/idp/client.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/config; 20 | import ballerina/http; 21 | 22 | function getBasicAuthIDPClient(string username, string password) returns http:Client { 23 | http:Client basicAuthClientEP = new(config:getAsString("idp.endpoint"), config = { 24 | secureSocket: { 25 | trustStore: { 26 | path: config:getAsString("security.truststore"), 27 | password: config:getAsString("security.truststorepass") 28 | }, 29 | verifyHostname: false 30 | }, 31 | auth: { 32 | scheme: http:BASIC_AUTH, 33 | config: { 34 | username: username, 35 | password: password 36 | } 37 | } 38 | }); 39 | return basicAuthClientEP; 40 | } 41 | -------------------------------------------------------------------------------- /components/api/docker_registry/docker_auth_client.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/http; 20 | import ballerina/config; 21 | 22 | function getDockerAuthClient(string userName, string token) returns http:Client { 23 | http:Client dockerAuthClientEP = new(config:getAsString("docker.auth.url"), config = { 24 | auth: { 25 | scheme: http:BASIC_AUTH, 26 | config: { 27 | username: userName, 28 | password: token 29 | } 30 | }, 31 | secureSocket: { 32 | trustStore: { 33 | path: config:getAsString("security.truststore"), 34 | password: config:getAsString("security.truststorepass") 35 | }, 36 | verifyHostname: false 37 | } 38 | }); 39 | return dockerAuthClientEP; 40 | } 41 | -------------------------------------------------------------------------------- /docker/proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM ballerina/ballerina:0.991.0 as builder 20 | LABEL MAINTAINER="WSO2 Cellery Maintainers " 21 | 22 | ARG PROJECT_DIR="/workspace" 23 | WORKDIR ${PROJECT_DIR} 24 | USER root 25 | 26 | COPY ./target/ ./ 27 | 28 | RUN chown -R ballerina ${PROJECT_DIR} 29 | USER ballerina 30 | 31 | # Experimental features enabled to use transactions 32 | RUN ballerina build --experimental 33 | 34 | FROM ballerina/ballerina:0.991.0 35 | 36 | ARG WORK_DIR="/home/ballerina" 37 | WORKDIR ${WORK_DIR} 38 | USER ballerina 39 | 40 | COPY --from=builder /workspace/target/registry_proxy.balx ./ 41 | 42 | RUN wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar -P ${BALLERINA_HOME}/bre/lib 43 | 44 | EXPOSE 9090 45 | 46 | ENTRYPOINT cp ${PROXY_CONF} ./ballerina.conf && ballerina run registry_proxy.balx 2>&1 | tee registry_proxy.log 47 | -------------------------------------------------------------------------------- /components/api/docker_registry/registry_client.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/config; 20 | import ballerina/http; 21 | 22 | function getOAuth2RegistryClient(string bearerToken) returns http:Client { 23 | http:Client dockerRegistryClient = new(config:getAsString("docker.registry.url"), config = { 24 | auth: { 25 | scheme: http:OAUTH2, 26 | config: { 27 | grantType: http:DIRECT_TOKEN, 28 | config: { 29 | accessToken: bearerToken 30 | } 31 | } 32 | }, 33 | secureSocket: { 34 | trustStore: { 35 | path: config:getAsString("security.truststore"), 36 | password: config:getAsString("security.truststorepass") 37 | }, 38 | verifyHostname: false 39 | } 40 | }); 41 | return dockerRegistryClient; 42 | } 43 | -------------------------------------------------------------------------------- /components/docker-auth/pkg/auth/authz_handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package auth 20 | 21 | import ( 22 | "fmt" 23 | 24 | "database/sql" 25 | 26 | "github.com/cesanta/docker_auth/auth_server/api" 27 | "go.uber.org/zap" 28 | 29 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/extension" 30 | ) 31 | 32 | func Authorize(dbConn *sql.DB, ai *api.AuthRequestInfo, logger *zap.SugaredLogger, execId string) (bool, error) { 33 | logger.Debugf("[%s] Authorization logic handler reached and access will be validated", execId) 34 | isValid, err := extension.IsUserAuthorized(dbConn, ai.Actions, ai.Account, ai.Name, ai.Labels, logger, execId) 35 | if err != nil { 36 | return false, fmt.Errorf("[%s] Error occurred while validating the user :%s", execId, err) 37 | } 38 | if isValid { 39 | logger.Debugf("[%s] Authorized user. Access granted by authz handler", execId) 40 | return true, nil 41 | } else { 42 | logger.Debugf("[%s] User access denied by authz handler", execId) 43 | return false, nil 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /components/portal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wso2-cellery/hub-portal", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^4.0.0", 7 | "@material-ui/icons": "^3.0.2", 8 | "axios": "^0.18.0", 9 | "classnames": "^2.2.6", 10 | "jwt-decode": "^2.2.0", 11 | "material-ui-chip-input": "^1.0.0-beta.17", 12 | "moment": "^2.24.0", 13 | "mui-datatables": "^2.3.0", 14 | "prop-types": "^15.7.2", 15 | "react": "^16.8.6", 16 | "react-dom": "^16.8.6", 17 | "react-google-recaptcha": "^1.0.5", 18 | "react-markdown": "^4.1.0", 19 | "react-router-dom": "^5.0.0", 20 | "react-scripts": "3.0.0", 21 | "typeface-roboto": "0.0.54", 22 | "vis": "^4.21.0" 23 | }, 24 | "scripts": { 25 | "start": "concurrently --kill-others --names \"config-server,webpack-dev-server\" \"APP_ENV=DEV PORTAL_PORT=4000 node node-server/serve.js\" \"HTTPS=true HOST=hub.cellery.io PORT=443 react-scripts start\"", 26 | "build": "react-scripts build", 27 | "lint": "eslint --color src/", 28 | "lint:fix": "eslint --color --fix src/", 29 | "test": "react-scripts test --colors --testURL=http://hub.cellery.io --coverage --watchAll=false", 30 | "eject": "react-scripts eject" 31 | }, 32 | "eslintConfig": { 33 | "extends": "react-app" 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.2%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | }, 47 | "devDependencies": { 48 | "concurrently": "^4.1.0", 49 | "eslint": "^5.16.0", 50 | "eslint-plugin-jest": "^22.1.3" 51 | }, 52 | "proxy": "http://localhost:4000" 53 | } 54 | -------------------------------------------------------------------------------- /docker/docker-auth/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM wso2cellery/docker-auth-base:82573a5f102c2d886428415bf6fcb8d94706834a AS build-env 20 | RUN mkdir -p /go/src/github.com/cellery-io/cellery-hub/components/docker-auth 21 | COPY ./target /go/src/github.com/cellery-io/cellery-hub/components/docker-auth/ 22 | ENV GO111MODULE=on 23 | RUN cd /go/src/github.com/cellery-io/cellery-hub/components/docker-auth/ && echo "replace github.com/cesanta/docker_auth/auth_server v0.0.0-20190831165929-82573a5f102c => /go/src/github.com/cesanta/docker_auth/auth_server" >> go.mod 24 | RUN cd /go/src/github.com/cellery-io/cellery-hub/components/docker-auth/ && go build -buildmode=plugin -o /plugins/authz.so cmd/authz/authorization.go 25 | RUN cd /go/src/github.com/cellery-io/cellery-hub/components/docker-auth/ && go build -buildmode=plugin -o /plugins/authn.so cmd/authn/authentication.go 26 | 27 | FROM ubuntu:18.04 28 | COPY --from=build-env /go/src/github.com/cesanta/docker_auth/auth_server/main / 29 | COPY --from=build-env /plugins/ /plugins/ 30 | 31 | ENTRYPOINT ["/main"] 32 | EXPOSE 5001 33 | -------------------------------------------------------------------------------- /components/portal/src/components/appLayout/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Container from "@material-ui/core/Container"; 20 | import Footer from "./Footer"; 21 | import Header from "./Header"; 22 | import React from "react"; 23 | import {withStyles} from "@material-ui/core/styles"; 24 | import * as PropTypes from "prop-types"; 25 | 26 | const styles = () => ({ 27 | root: { 28 | display: "flex", 29 | minHeight: "100vh", 30 | flexDirection: "column" 31 | }, 32 | mainContent: { 33 | flex: 1 34 | } 35 | }); 36 | 37 | const AppLayout = (props) => { 38 | const {classes, children} = props; 39 | 40 | return ( 41 |
42 |
43 |
44 | 45 | {children} 46 | 47 |
48 |
49 |
50 | ); 51 | }; 52 | 53 | AppLayout.propTypes = { 54 | classes: PropTypes.object.isRequired, 55 | children: PropTypes.any.isRequired 56 | }; 57 | 58 | export default withStyles(styles)(AppLayout); 59 | 60 | -------------------------------------------------------------------------------- /components/portal/src/utils/api/dataUtils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | /** 20 | * Data (returned from the API) related utilities. 21 | */ 22 | class DataUtils { 23 | 24 | /** 25 | * Get the name to be displayed for a user object returned from the API. 26 | * 27 | * @param {Object} userData The user data object returned from the API. 28 | * @returns {string} The display name to be used in the Portal 29 | */ 30 | static getUserDisplayName(userData) { 31 | let displayName = ""; 32 | if (userData) { 33 | if (userData.displayName) { 34 | displayName = userData.displayName; 35 | } else if (userData.email) { 36 | displayName = userData.email.split("@")[0]; 37 | } else { 38 | throw Error("Either the displayName or the email need to be present in the provided user, " 39 | + `received ${JSON.stringify(userData)}`); 40 | } 41 | } else { 42 | throw Error(`Unable to get display for empty user data, received ${userData}`); 43 | } 44 | return displayName; 45 | } 46 | 47 | } 48 | 49 | export default DataUtils; 50 | -------------------------------------------------------------------------------- /components/portal/src/components/sdk/appLayout/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Container from "@material-ui/core/Container"; 20 | import Footer from "../../appLayout/Footer"; 21 | import Header from "./Header"; 22 | import React from "react"; 23 | import {withStyles} from "@material-ui/core/styles"; 24 | import * as PropTypes from "prop-types"; 25 | 26 | const styles = () => ({ 27 | root: { 28 | display: "flex", 29 | minHeight: "100vh", 30 | flexDirection: "column" 31 | }, 32 | mainContent: { 33 | flex: 1 34 | } 35 | }); 36 | 37 | const SDKAppLayout = (props) => { 38 | const {classes, children} = props; 39 | 40 | return ( 41 |
42 |
43 |
44 | 45 | {children} 46 | 47 |
48 |
49 |
50 | ); 51 | }; 52 | 53 | SDKAppLayout.propTypes = { 54 | classes: PropTypes.object.isRequired, 55 | children: PropTypes.any.isRequired 56 | }; 57 | 58 | export default withStyles(styles)(SDKAppLayout); 59 | 60 | -------------------------------------------------------------------------------- /components/proxy/database/lock.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/log; 20 | 21 | # Acquire the write lock from the MySQL DB. 22 | # 23 | # Lock this path by acquiring the MySQL write lock. Since this is in a transaction auto commit will be switched off. 24 | # This allows the proxy to run in HA mode and lock the image pushing across replicas. 25 | # 26 | # + imageFQN - imageFQN Fully qualified Cell Image name 27 | # + return - error if an error occurred 28 | public function acquireWriteLockForImage(string imageFQN) returns error? { 29 | _ = check celleryHubDB->update(LOCK_QUERY, imageFQN); 30 | } 31 | 32 | # Cleanup any data usd in acquiring the write lock. 33 | # 34 | # + imageFQN - imageFQN Parameter Description 35 | public function cleanUpAfterLockForImage(string imageFQN) { 36 | var lockCleanupResult = celleryHubDB->update(DELETE_LOCK_ENTRIES_QUERY, imageFQN); 37 | if (lockCleanupResult is error) { 38 | log:printError("Failed to cleanup lock rows created for image " + imageFQN, err = lockCleanupResult); 39 | } else { 40 | log:printDebug("Removed DB row used for locking image " + imageFQN); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /components/portal/src/utils/constants.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | const Constants = { 20 | Color: { 21 | SUCCESS: "#23ff5d", 22 | ERROR: "#ff443d" 23 | }, 24 | Pattern: { 25 | CELLERY_ID: "[a-z0-9]+(-[a-z0-9]+)*", 26 | PARTIAL_CELLERY_ID: "[-a-z0-9]+", 27 | PARTIAL_IMAGE_VERSION: "[-.a-z0-9]+", 28 | PARTIAL_IMAGE_FQN: "((?:-?[a-z0-9]+)+)(?:/([a-z0-9]+))?[-a-z0-9]*" 29 | }, 30 | Format: { 31 | DATE_TIME: "DD MMM YYYY, hh:mm:ss A" 32 | }, 33 | Visibility: { 34 | PUBLIC: "PUBLIC", 35 | PRIVATE: "PRIVATE" 36 | }, 37 | SortingOrder: { 38 | MOST_POPULAR: "most-popular", 39 | RECENTLY_UPDATED: "last-updated" 40 | }, 41 | KeyCode: { 42 | ENTER: 13 43 | }, 44 | Header: { 45 | CELLERY_HUB_CAPTCHA: "g-recaptcha-response" 46 | }, 47 | ApplicationErrorCode: { 48 | ALREADY_EXISTS: 2, 49 | ALLOWED_LIMIT_EXCEEDED: 3, 50 | ENTRY_NOT_FOUND: 4 51 | }, 52 | Permission: { 53 | ADMIN: "admin", 54 | PUSH: "push", 55 | PULL: "pull" 56 | }, 57 | Type: { 58 | CELL: "Cell", 59 | COMPOSITE: "Composite" 60 | } 61 | }; 62 | 63 | export default Constants; 64 | -------------------------------------------------------------------------------- /components/api/core/response_handler.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | public function buildErrorResponse(int statusCode, int code, string message, string description) returns http:Response { 20 | http:Response res = new; 21 | gen:ErrorResponse errPassed = { 22 | code: code, 23 | message: message, 24 | description: description 25 | }; 26 | var errJson = json.convert(errPassed); 27 | if (errJson is json) { 28 | res.setJsonPayload(errJson); 29 | res.statusCode = statusCode; 30 | } else { 31 | res = buildUnknownErrorResponse(); 32 | } 33 | return res; 34 | } 35 | 36 | function buildUnknownErrorResponse() returns http:Response { 37 | http:Response res = new; 38 | json errDefault = { 39 | code: constants:API_ERROR_CODE, 40 | message: "Unexpected error occurred", 41 | description: "" 42 | }; 43 | res.setPayload(errDefault); 44 | res.statusCode = http:INTERNAL_SERVER_ERROR_500; 45 | return res; 46 | } 47 | 48 | function buildSuccessResponse(json jsonResponse = null) returns http:Response { 49 | http:Response resp = new; 50 | resp.statusCode = http:OK_200; 51 | resp.setJsonPayload(untaint jsonResponse); 52 | return resp; 53 | } 54 | -------------------------------------------------------------------------------- /components/identity-server-customization/cellery-identity-customizations/src/main/java/io/cellery/hub/identity/extension/internal/CelleryCustomizationDataHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.cellery.hub.identity.extension.internal; 20 | 21 | import org.wso2.carbon.registry.core.service.RegistryService; 22 | import org.wso2.carbon.user.core.service.RealmService; 23 | 24 | /** 25 | * Keep services aquired through OSGI. 26 | */ 27 | public class CelleryCustomizationDataHolder { 28 | 29 | private RealmService realmService = null; 30 | private RegistryService registryService = null; 31 | private static CelleryCustomizationDataHolder instance = new CelleryCustomizationDataHolder(); 32 | 33 | public static CelleryCustomizationDataHolder getInstance() { 34 | 35 | return instance; 36 | } 37 | 38 | private CelleryCustomizationDataHolder() { 39 | 40 | } 41 | 42 | public RegistryService getRegistryService() { 43 | 44 | return registryService; 45 | } 46 | 47 | public void setRegistryService(RegistryService registryService) { 48 | 49 | this.registryService = registryService; 50 | } 51 | 52 | public RealmService getRealmService() { 53 | 54 | return realmService; 55 | } 56 | 57 | public void setRealmService(RealmService realmService) { 58 | 59 | this.realmService = realmService; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /docker/identity-server/Dockerfile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2018 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | FROM wso2cellery/cellery-hub-idp-base:5.8.0 20 | 21 | ARG USER_HOME=/home/wso2carbon 22 | ARG FILES=./target/files 23 | ARG AUTHENTICATION_ENDPOINT_WEBAPP=${USER_HOME}/wso2is-5.8.0/repository/deployment/server/webapps/authenticationendpoint 24 | 25 | # Copy the jar files 26 | COPY --chown=wso2carbon:wso2 ${FILES}/dropins/** ${USER_HOME}/wso2is-5.8.0/repository/components/dropins/ 27 | 28 | # Copy the error pages 29 | 30 | RUN mkdir ${AUTHENTICATION_ENDPOINT_WEBAPP} 31 | 32 | RUN cd ${AUTHENTICATION_ENDPOINT_WEBAPP}; \ 33 | jar -xvf ${AUTHENTICATION_ENDPOINT_WEBAPP}.war 34 | 35 | COPY --chown=wso2carbon:wso2 ${FILES}/authenticationendpoint/css/custom-common.css ${AUTHENTICATION_ENDPOINT_WEBAPP}/css/custom-common.css 36 | COPY --chown=wso2carbon:wso2 ${FILES}/authenticationendpoint/images/ ${AUTHENTICATION_ENDPOINT_WEBAPP}/images/ 37 | COPY --chown=wso2carbon:wso2 ${FILES}/authenticationendpoint/cellery_error.jsp ${AUTHENTICATION_ENDPOINT_WEBAPP}/oauth2_error.jsp 38 | COPY --chown=wso2carbon:wso2 ${FILES}/authenticationendpoint/cellery_error.jsp ${AUTHENTICATION_ENDPOINT_WEBAPP}/retry.jsp 39 | COPY --chown=wso2carbon:wso2 ${FILES}/authenticationendpoint/localize/* ${AUTHENTICATION_ENDPOINT_WEBAPP}/WEB-INF/classes/org/wso2/carbon/identity/application/authentication/endpoint/i18n/ 40 | -------------------------------------------------------------------------------- /components/portal/src/components/explore/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import CustomizedTabs from "../common/CustomizedTabs"; 20 | import Divider from "@material-ui/core/Divider"; 21 | import Images from "./Images"; 22 | import Orgs from "./Orgs"; 23 | import React from "react"; 24 | import Typography from "@material-ui/core/Typography"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import * as PropTypes from "prop-types"; 27 | 28 | const styles = (theme) => ({ 29 | content: { 30 | paddingTop: theme.spacing(4) 31 | }, 32 | divider: { 33 | marginBottom: theme.spacing(4) 34 | } 35 | }); 36 | 37 | const Explore = (props) => { 38 | const {classes} = props; 39 | const tabs = [ 40 | { 41 | label: "Images", 42 | render: () => 43 | }, 44 | { 45 | label: "Organizations", 46 | render: () => 47 | } 48 | ]; 49 | return ( 50 |
51 | 52 | Explore 53 | 54 | 55 | 56 |
57 | ); 58 | }; 59 | 60 | Explore.propTypes = { 61 | classes: PropTypes.object.isRequired 62 | }; 63 | 64 | export default withStyles(styles)(Explore); 65 | -------------------------------------------------------------------------------- /components/docker-auth/pkg/extension/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package extension 20 | 21 | const userAdminRole = "admin" 22 | const userPushRole = "push" 23 | 24 | const MysqlUserEnvVar = "MYSQL_USER" 25 | const MysqlPasswordEnvVar = "MYSQL_PASSWORD" 26 | const MysqlHostEnvVar = "MYSQL_HOST" 27 | const MysqlPortEnvVar = "MYSQL_PORT" 28 | const MysqlDriver = "mysql" 29 | const DbName = "CELLERY_HUB" 30 | const IdpUsernameEnvVar = "USERNAME" 31 | const IdppasswordEnvVar = "PASSWORD" 32 | 33 | const MaxOpenConnectionsEnvVar = "MAX_OPEN_CONNECTIONS" 34 | const MaxIdleConnectionsEnvVar = "MAX_IDLE_CONNECTIONS" 35 | const ConnectionMaxLifetimeEnvVar = "MAX_LIFE_TIME" 36 | 37 | const pullAction = "pull" 38 | const pushAction = "push" 39 | const deleteAction = "delete" 40 | const publicVisibility = "PUBLIC" 41 | 42 | // db queries 43 | const getVisibilityQuery = "SELECT VISIBILITY FROM REGISTRY_ARTIFACT_IMAGE " + 44 | "INNER JOIN REGISTRY_ORGANIZATION ON REGISTRY_ORGANIZATION.ORG_NAME=REGISTRY_ARTIFACT_IMAGE.ORG_NAME " + 45 | "WHERE REGISTRY_ARTIFACT_IMAGE.IMAGE_NAME=? AND " + 46 | "REGISTRY_ORGANIZATION.ORG_NAME=? LIMIT 1" 47 | const getUserAvailabilityQuery = "SELECT 1 FROM " + 48 | "REGISTRY_ORG_USER_MAPPING " + 49 | "WHERE REGISTRY_ORG_USER_MAPPING.USER_UUID=? AND REGISTRY_ORG_USER_MAPPING.ORG_NAME=?" 50 | const getUserRoleQuery = "SELECT USER_ROLE FROM " + 51 | "REGISTRY_ORG_USER_MAPPING " + 52 | "WHERE REGISTRY_ORG_USER_MAPPING.USER_UUID=? AND REGISTRY_ORG_USER_MAPPING.ORG_NAME=?" 53 | -------------------------------------------------------------------------------- /components/api/docker_registry/auth_token.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/http; 20 | import ballerina/io; 21 | import cellery_hub_api/constants; 22 | 23 | public function getTokenFromDockerAuth(string userName, string token, string registryScope) returns string | error? { 24 | log:printDebug(io:sprintf("Invoking docker auth API for get token for scope : %s", registryScope)); 25 | 26 | string | error registryServiceName = http:encode(constants:DOCKER_REGISTRY_SERVICE_NAME, "utf-8"); 27 | 28 | if (registryServiceName is string) { 29 | string getTokenPathParams = io:sprintf("/auth?service=%s&scope=%s", registryServiceName, registryScope); 30 | http:Client dockerAuthClient = getDockerAuthClient(userName, token); 31 | var authResponse = dockerAuthClient->get(getTokenPathParams, message = ""); 32 | if (authResponse is http:Response) { 33 | var authPayload = authResponse.getJsonPayload(); 34 | if (authPayload is json) { 35 | return authPayload["token"].toString(); 36 | } 37 | } else { 38 | error er = error(io:sprintf("Error when calling the dockerAuthClient. %s", authResponse.reason())); 39 | return er; 40 | } 41 | } else { 42 | error er = error(io:sprintf("Error when encoding the registry service name. %s", registryServiceName.reason())); 43 | return er; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /components/api/validator/configReader.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/io; 20 | import ballerina/log; 21 | import ballerina/system; 22 | import ballerina/filepath; 23 | import ballerina/config; 24 | import cellery_hub_api/constants; 25 | 26 | public type Conf record { | 27 | string introspectionEp = constants:DEFAULT_IDP_ENDPOINT; 28 | string username = constants:IDP_DEFAULT_USERNAME; 29 | string password = constants:IDP_DEFAULT_PASSWORD; 30 | | }; 31 | 32 | Conf config = {}; 33 | boolean configLoaded = false; 34 | public function getAuthConfig() returns (Conf)|error { 35 | if configLoaded == true { 36 | return config; 37 | } 38 | log:printDebug("Started to read config file"); 39 | if (config:getAsString(constants:IDP_INTROSPCET_VAR) != "" && config:getAsString(constants:IDP_USERNAME_VAR) != "" && 40 | config:getAsString(constants:IDP_PASSWORD_VAR) != "") { 41 | config = { 42 | introspectionEp:config:getAsString(constants:IDP_ENDPOINT_VAR) + config:getAsString 43 | (constants:IDP_INTROSPCET_VAR), 44 | username:config:getAsString(constants:IDP_USERNAME_VAR), 45 | password:config:getAsString(constants:IDP_PASSWORD_VAR) 46 | }; 47 | } else { 48 | log:printInfo("Could not resolve the values from configs. Hence using the default values"); 49 | } 50 | configLoaded = true; 51 | return config; 52 | } 53 | -------------------------------------------------------------------------------- /components/docker-auth/test/data.sql: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | USE CELLERY_HUB; 20 | INSERT INTO `REGISTRY_ORGANIZATION` (ORG_NAME, DESCRIPTION, WEBSITE_URL, DEFAULT_IMAGE_VISIBILITY, FIRST_AUTHOR, CREATED_DATE) VALUES ('cellery','ABC is my first org','abc.com','private','unknown','2019-05-27 14:58:47'); 21 | INSERT INTO `REGISTRY_ORGANIZATION` (ORG_NAME, DESCRIPTION, WEBSITE_URL, DEFAULT_IMAGE_VISIBILITY, FIRST_AUTHOR, CREATED_DATE) VALUES ('is','ABC is my first org','pqr.com','private','unknown','2019-05-27 14:58:47'); 22 | INSERT INTO `REGISTRY_ORG_USER_MAPPING` (USER_UUID, ORG_NAME, USER_ROLE, CREATED_DATE) VALUES ('wso2.com','cellery','push','2019-04-06 00:00:00'); 23 | INSERT INTO `REGISTRY_ORG_USER_MAPPING` (USER_UUID, ORG_NAME, USER_ROLE, CREATED_DATE) VALUES ('admin.com','cellery','admin','2019-04-06 00:00:00'); 24 | INSERT INTO `REGISTRY_ORG_USER_MAPPING` (USER_UUID, ORG_NAME, USER_ROLE, CREATED_DATE) VALUES ('other.com','is','pull','2019-04-06 00:00:00'); 25 | INSERT INTO `REGISTRY_ARTIFACT_IMAGE` (ARTIFACT_IMAGE_ID, ORG_NAME, IMAGE_NAME, DESCRIPTION, FIRST_AUTHOR, VISIBILITY) VALUES ('1','cellery','image','Sample','unkown','PUBLIC'); 26 | INSERT INTO `REGISTRY_ARTIFACT_IMAGE` (ARTIFACT_IMAGE_ID, ORG_NAME, IMAGE_NAME, DESCRIPTION, FIRST_AUTHOR, VISIBILITY) VALUES ('2','cellery','newImage','Sample','www.dockehub.com','PRIVATE'); 27 | INSERT INTO `REGISTRY_ARTIFACT_IMAGE` (ARTIFACT_IMAGE_ID, ORG_NAME, IMAGE_NAME, DESCRIPTION, FIRST_AUTHOR, VISIBILITY) VALUES ('3','is','pqr','Sample','www.dockehub.com','PRIVATE'); 28 | -------------------------------------------------------------------------------- /components/docker-auth/cmd/authz/authorization.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | 24 | "github.com/cesanta/docker_auth/auth_server/api" 25 | "go.uber.org/zap" 26 | 27 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/auth" 28 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/db" 29 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/extension" 30 | ) 31 | 32 | var logger *zap.SugaredLogger 33 | 34 | type PluginAuthz struct { 35 | } 36 | 37 | func (*PluginAuthz) Stop() { 38 | } 39 | 40 | func (*PluginAuthz) Name() string { 41 | return "plugin authz" 42 | } 43 | 44 | func (c *PluginAuthz) Authorize(ai *api.AuthRequestInfo) ([]string, error) { 45 | if logger == nil { 46 | logger = extension.NewLogger() 47 | } 48 | return doAuthorize(ai, logger) 49 | } 50 | 51 | var Authz PluginAuthz 52 | 53 | func doAuthorize(ai *api.AuthRequestInfo, logger *zap.SugaredLogger) ([]string, error) { 54 | execId, err := extension.GetExecID(logger) 55 | if err != nil { 56 | return nil, fmt.Errorf("error in generating the execId : %s", err) 57 | } 58 | logger.Debugf("Authorization logic reached. User will be authorized") 59 | dbConnectionPool, err := db.GetDbConnectionPool(logger) 60 | if err != nil { 61 | return nil, fmt.Errorf("error while establishing database connection pool: %v", err) 62 | } 63 | authorized, err := auth.Authorize(dbConnectionPool, ai, logger, execId) 64 | if err != nil { 65 | return nil, fmt.Errorf("error while executing authorization logic: %v", err) 66 | } 67 | if !authorized { 68 | logger.Debugf("[%s] User : %s is unauthorized for %s actions", execId, ai.Account, ai.Actions) 69 | return nil, nil 70 | } else { 71 | logger.Debugf("[%s] User : %s is authorized for %s actions", execId, ai.Account, ai.Actions) 72 | return ai.Actions, nil 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /components/portal/node-server/serve.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | const path = require("path"); 20 | const fs = require("fs"); 21 | const https = require("https"); 22 | const express = require("express"); 23 | const fallback = require("express-history-api-fallback"); 24 | 25 | let app = express(); 26 | const webPortalPort = process.env.PORTAL_PORT || 3000; 27 | 28 | const configRoot = path.join(__dirname, "/config"); 29 | const portalConfigFile = `${configRoot}/portal.json`; 30 | console.log(`Using Portal Configuration from ${portalConfigFile} file`); 31 | 32 | let portalConfig; 33 | const loadPortalConfig = () => { 34 | portalConfig = fs.readFileSync(`${portalConfigFile}`, "utf8"); 35 | console.log("Loaded new Portal Configuration"); 36 | }; 37 | loadPortalConfig(); 38 | 39 | // Watching for config changes 40 | fs.watch(configRoot, null, () => { 41 | loadPortalConfig(); 42 | }); 43 | 44 | // REST API for configurations 45 | app.get("/config", (req, res) => { 46 | res.set("Content-Type", "application/json"); 47 | res.send(portalConfig); 48 | }); 49 | 50 | if (process.env.APP_ENV !== "DEV") { 51 | const appRoot = path.join(__dirname, "/public"); 52 | console.log(`Using App from ${appRoot} directory`); 53 | 54 | // Serving the React App 55 | app.use(express.static(appRoot)); 56 | app.use(fallback("index.html", { 57 | root: appRoot 58 | })); 59 | 60 | // Creating an HTTPS server for production 61 | app = https.createServer({ 62 | key: fs.readFileSync(process.env.PORTAL_PRIVATE_KEY), 63 | cert: fs.readFileSync(process.env.PORTAL_CERT) 64 | }, app); 65 | } else { 66 | console.log("Serving Only the Hub Portal Configuration"); 67 | } 68 | 69 | const server = app.listen(webPortalPort, () => { 70 | const host = server.address().address; 71 | const port = server.address().port; 72 | 73 | console.log("Cellery Hub Portal listening at http://%s:%s", host, port); 74 | }); 75 | -------------------------------------------------------------------------------- /components/proxy/docker_registry/registry.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/io; 20 | import ballerina/config; 21 | import ballerina/http; 22 | 23 | http:Client dockerRegistryClientEP = new(config:getAsString("docker.registry.url"), config = { 24 | secureSocket: { 25 | trustedCertFile: config:getAsString("security.trustedcertsfile"), 26 | verifyHostname: false 27 | } 28 | 29 | }); 30 | 31 | # Forward a request to the Docker Rgistry. 32 | # 33 | # + req - The request to be forwared to the docker registry 34 | # + return - The response received from the registry 35 | public function forwardRequest(http:Request req) returns (http:Response|error) { 36 | return dockerRegistryClientEP->forward(untaint req.rawPath, req); 37 | } 38 | 39 | # Pull a file layer from the Docker Registry. 40 | # 41 | # + repository - The Docker Image Repository name 42 | # + fileLayer - Docker File Layer to be pulled 43 | # + jwtToken - The JWT token that should be used 44 | # + return - Docker file layer bytes 45 | public function pullDockerFileLayer(string repository, string fileLayer, string jwtToken) returns (byte[]|error) { 46 | http:Request dockerRegistryRequest = new; 47 | dockerRegistryRequest.addHeader("Authorization", "Bearer " + jwtToken); 48 | var response = check dockerRegistryClientEP->get(io:sprintf("/v2/%s/blobs/%s", repository, fileLayer), 49 | message = dockerRegistryRequest); 50 | if (response.statusCode >= 200 && response.statusCode < 400) { 51 | return response.getBinaryPayload(); 52 | } else if (response.statusCode == 401) { 53 | error err = error("unauthorized to pull docker file layer " + fileLayer); 54 | return err; 55 | } else { 56 | error err = error(io:sprintf("failed to pull docker file layer %s with status code %s", fileLayer, 57 | response.statusCode)); 58 | return err; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | > Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc. 3 | 4 | ## Goals 5 | > Describe the solutions that this feature/fix will introduce to resolve the problems described above 6 | 7 | ## Approach 8 | > Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here. 9 | 10 | ## User stories 11 | > Summary of user stories addressed by this change> 12 | 13 | ## Release note 14 | > Brief description of the new feature or bug fix as it will appear in the release notes 15 | 16 | ## Documentation 17 | > Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact 18 | 19 | ## Training 20 | > Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable 21 | 22 | ## Certification 23 | > Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why. 24 | 25 | ## Marketing 26 | > Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable 27 | 28 | ## Automation tests 29 | - Unit tests 30 | > Code coverage information 31 | - Integration tests 32 | > Details about the test cases and coverage 33 | 34 | ## Security checks 35 | - Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes/no 36 | - Ran FindSecurityBugs plugin and verified report? yes/no 37 | - Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes/no 38 | 39 | ## Samples 40 | > Provide high-level details about the samples related to this feature 41 | 42 | ## Related PRs 43 | > List any other related PRs 44 | 45 | ## Migrations (if applicable) 46 | > Describe migration steps and platforms on which migration has been tested 47 | 48 | ## Test environment 49 | > List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested 50 | 51 | ## Learning 52 | > Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem. -------------------------------------------------------------------------------- /components/portal/src/components/common/error/ErrorBoundary.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import React from "react"; 18 | import UnknownError from "./UnknownError"; 19 | import * as PropTypes from "prop-types"; 20 | 21 | /* eslint no-console: ["off"] */ 22 | 23 | /** 24 | * Error Boundary to catch error in React Components. 25 | * This Component can be used to wrap areas of the React App and catch any errors that occur inside them. 26 | * 27 | * Example:- A graph can be wrapped and the title can be set to "Invalid Data" to make sure that the users sees 28 | * this message instead of a blank screen if an error occurs. 29 | * 30 | * This will not affect the dev servers and the errors will still be shown. 31 | * 32 | * @returns {React.Component} Error Boundary React Component 33 | */ 34 | class ErrorBoundary extends React.Component { 35 | 36 | constructor(props) { 37 | super(props); 38 | 39 | this.state = { 40 | hasError: false 41 | }; 42 | } 43 | 44 | /** 45 | * Derive a suitable state from the error if any error occurs. 46 | * 47 | * @param {Error} error The error that occurred 48 | * @returns {Object} New state 49 | */ 50 | static getDerivedStateFromError = (error) => { 51 | console.error(error); 52 | return { 53 | hasError: true 54 | }; 55 | }; 56 | 57 | render = () => { 58 | const {children, title, description, showNavigationButtons} = this.props; 59 | const {hasError} = this.state; 60 | 61 | let content; 62 | if (hasError) { 63 | content = ( 64 | 65 | ); 66 | } else { 67 | content = children; 68 | } 69 | return content; 70 | }; 71 | 72 | } 73 | 74 | ErrorBoundary.propTypes = { 75 | children: PropTypes.any.isRequired, 76 | title: PropTypes.string, 77 | description: PropTypes.string, 78 | showNavigationButtons: PropTypes.bool 79 | }; 80 | 81 | export default ErrorBoundary; 82 | -------------------------------------------------------------------------------- /components/portal/src/components/appLayout/ButtonAppBarCollapse.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import IconButton from "@material-ui/core/IconButton"; 20 | import Menu from "@material-ui/core/Menu"; 21 | import MenuIcon from "@material-ui/icons/Menu"; 22 | import React from "react"; 23 | import {withStyles} from "@material-ui/core/styles"; 24 | import * as PropTypes from "prop-types"; 25 | 26 | const styles = (theme) => ({ 27 | buttonCollapse: { 28 | [theme.breakpoints.up("md")]: { 29 | display: "none" 30 | }, 31 | margin: 10, 32 | boxShadow: "none" 33 | } 34 | }); 35 | 36 | class ButtonAppBarCollapse extends React.Component { 37 | 38 | constructor(props) { 39 | super(props); 40 | this.state = { 41 | anchorEl: null 42 | }; 43 | this.handleMenu = this.handleMenu.bind(this); 44 | } 45 | 46 | handleMenu = (event) => { 47 | this.setState({anchorEl: event.currentTarget}); 48 | }; 49 | 50 | handleClose = () => { 51 | this.setState({anchorEl: null}); 52 | }; 53 | 54 | render() { 55 | const {classes, children} = this.props; 56 | const {anchorEl} = this.state; 57 | const open = Boolean(anchorEl); 58 | 59 | return ( 60 |
61 | 62 | 63 | 64 | 77 | {children} 78 | 79 |
80 | ); 81 | } 82 | 83 | } 84 | 85 | ButtonAppBarCollapse.propTypes = { 86 | classes: PropTypes.object.isRequired, 87 | children: PropTypes.any.isRequired 88 | 89 | }; 90 | 91 | export default withStyles(styles)(ButtonAppBarCollapse); 92 | -------------------------------------------------------------------------------- /components/portal/src/components/appLayout/Header.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import AppBar from "@material-ui/core/AppBar"; 20 | import CelleryLogo from "../../img/celleryLogo.svg"; 21 | import Container from "@material-ui/core/Container"; 22 | import NavBar from "./NavBar"; 23 | import React from "react"; 24 | import Toolbar from "@material-ui/core/Toolbar"; 25 | import {withRouter} from "react-router-dom"; 26 | import {withStyles} from "@material-ui/core/styles"; 27 | import * as PropTypes from "prop-types"; 28 | 29 | const styles = (theme) => ({ 30 | appbar: { 31 | backgroundColor: "#ffffff", 32 | color: theme.palette.primary.main, 33 | boxShadow: "none" 34 | }, 35 | headerLogo: { 36 | flexGrow: 1 37 | }, 38 | logo: { 39 | fontSize: 32, 40 | fontWeight: 400, 41 | color: "#43AB00", 42 | cursor: "pointer" 43 | }, 44 | celleryLogo: { 45 | height: 40, 46 | verticalAlign: "middle", 47 | paddingRight: 2 48 | }, 49 | toolbar: { 50 | paddingLeft: 0, 51 | paddingRight: 0 52 | }, 53 | headerContent: { 54 | borderBottom: "1px solid", 55 | borderBottomColor: theme.palette.primary.main 56 | } 57 | }); 58 | 59 | const Header = ({classes, history}) => ( 60 |
61 |
62 | 63 | 64 | 65 |
66 |
history.push("/")}> 67 | {"Cellery 68 | hub 69 |
70 |
71 | 72 |
73 |
74 |
75 |
76 |
77 | ); 78 | 79 | Header.propTypes = { 80 | classes: PropTypes.object.isRequired, 81 | history: PropTypes.shape({ 82 | push: PropTypes.func.isRequired 83 | }) 84 | }; 85 | 86 | export default withStyles(styles)(withRouter(Header)); 87 | -------------------------------------------------------------------------------- /components/portal/src/utils/common/notificationUtils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import {StateHolder} from "../../components/common/state"; 20 | 21 | class NotificationUtils { 22 | 23 | static Levels = { 24 | INFO: "INFO", 25 | WARNING: "WARNING", 26 | ERROR: "ERROR" 27 | }; 28 | 29 | /** 30 | * Show the loading overlay. 31 | * 32 | * @param {string} message The message to be shown in the loading overlay 33 | * @param {StateHolder} globalState The global state provided to the current component 34 | */ 35 | static showLoadingOverlay = (message, globalState) => { 36 | const prevState = globalState.get(StateHolder.LOADING_STATE); 37 | globalState.set(StateHolder.LOADING_STATE, { 38 | loadingOverlayCount: prevState.loadingOverlayCount + 1, 39 | message: message 40 | }); 41 | }; 42 | 43 | /** 44 | * Hide the loading overlay. 45 | * 46 | * @param {StateHolder} globalState The global state provided to the current component 47 | */ 48 | static hideLoadingOverlay = (globalState) => { 49 | const prevState = globalState.get(StateHolder.LOADING_STATE); 50 | globalState.set(StateHolder.LOADING_STATE, { 51 | loadingOverlayCount: prevState.loadingOverlayCount === 0 ? 0 : prevState.loadingOverlayCount - 1, 52 | message: null 53 | }); 54 | }; 55 | 56 | /** 57 | * Show a notification to the user. 58 | * 59 | * @param {string} message The message to be shown in the notification 60 | * @param {string} level The notification level 61 | * @param {StateHolder} globalState The global state provided to the current component 62 | */ 63 | static showNotification = (message, level, globalState) => { 64 | globalState.set(StateHolder.NOTIFICATION_STATE, { 65 | isOpen: true, 66 | message: message, 67 | notificationLevel: level 68 | }); 69 | }; 70 | 71 | /** 72 | * Close the notification shown to the user. 73 | * 74 | * @param {StateHolder} globalState The global state provided to the current component 75 | */ 76 | static closeNotification = (globalState) => { 77 | globalState.set(StateHolder.NOTIFICATION_STATE, { 78 | ...globalState.get(StateHolder.NOTIFICATION_STATE), 79 | isOpen: false 80 | }); 81 | }; 82 | 83 | } 84 | 85 | export default NotificationUtils; 86 | -------------------------------------------------------------------------------- /components/portal/src/components/common/Description.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import DescriptionOutlined from "@material-ui/icons/DescriptionOutlined"; 20 | import Grid from "@material-ui/core/Grid"; 21 | import Markdown from "react-markdown"; 22 | import React from "react"; 23 | import Typography from "@material-ui/core/Typography"; 24 | import {withRouter} from "react-router-dom"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import withGlobalState, {StateHolder} from "./state/index"; 27 | import * as PropTypes from "prop-types"; 28 | 29 | const styles = (theme) => ({ 30 | content: { 31 | paddingTop: theme.spacing(4) 32 | }, 33 | noDescriptionMsgContainer: { 34 | textAlign: "center", 35 | paddingTop: theme.spacing(6), 36 | paddingBottom: theme.spacing(4) 37 | }, 38 | descriptionIcon: { 39 | color: "#a0a0a0" 40 | }, 41 | noDescriptionMsg: { 42 | fontWeight: 500, 43 | color: "#a0a0a0", 44 | paddingTop: theme.spacing(1) 45 | } 46 | }); 47 | 48 | const VersionList = (props) => { 49 | const {classes, data} = props; 50 | 51 | return ( 52 |
53 |
54 | { 55 | data 56 | ? ( 57 | 58 | 59 | 60 | 61 | 62 | ) 63 | : ( 64 |
65 | 66 | 67 | No Description Found 68 | 69 |
70 | ) 71 | } 72 |
73 |
74 | ); 75 | }; 76 | 77 | VersionList.propTypes = { 78 | data: PropTypes.string, 79 | classes: PropTypes.object.isRequired, 80 | globalState: PropTypes.instanceOf(StateHolder).isRequired 81 | }; 82 | 83 | export default withStyles(styles)(withRouter(withGlobalState(VersionList))); 84 | -------------------------------------------------------------------------------- /components/portal/src/components/sdk/SignInFailure.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import CelleryCmd from "../../img/celleryCmd.png"; 20 | import ErrorOutlineRounded from "@material-ui/icons/ErrorOutlineRounded"; 21 | import Grid from "@material-ui/core/Grid"; 22 | import React from "react"; 23 | import Typography from "@material-ui/core/Typography"; 24 | import {withStyles} from "@material-ui/core/styles"; 25 | import withGlobalState, {StateHolder} from "../common/state"; 26 | import * as PropTypes from "prop-types"; 27 | 28 | const styles = (theme) => ({ 29 | content: { 30 | paddingTop: theme.spacing(4) 31 | }, 32 | success: { 33 | paddingTop: theme.spacing(2), 34 | paddingBottom: theme.spacing(4) 35 | }, 36 | gotoHub: { 37 | fontWeight: 400, 38 | paddingTop: theme.spacing(2), 39 | color: "#464646", 40 | textAlign: "center" 41 | }, 42 | hubUrl: { 43 | color: "#464646", 44 | textDecoration: "underline" 45 | }, 46 | celleryCmd: { 47 | height: 85, 48 | paddingTop: theme.spacing(2) 49 | }, 50 | error: { 51 | paddingTop: theme.spacing(2), 52 | color: "#e74c3c", 53 | fontSize: "3.8rem" 54 | }, 55 | nextTitle: { 56 | color: "#464646" 57 | } 58 | }); 59 | 60 | const SignInFailure = (props) => { 61 | const {classes} = props; 62 | return ( 63 |
64 | 65 | 66 | 67 | Authentication failure! 68 | 69 | What to do next? 70 | {"Cellery 71 |
72 | 73 | Go back to your terminal to know more information about the error and try login again. 74 | 75 |
76 | 77 |
78 |
79 | ); 80 | }; 81 | 82 | SignInFailure.propTypes = { 83 | classes: PropTypes.object.isRequired, 84 | globalState: PropTypes.instanceOf(StateHolder).isRequired 85 | }; 86 | 87 | export default withStyles(styles)(withGlobalState(SignInFailure)); 88 | -------------------------------------------------------------------------------- /docker/identity-server/resources/authenticationendpoint/images/logo-inverse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 11 | 23 | 24 | 27 | 28 | 31 | 33 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /components/proxy/database/queries.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | const string LOCK_QUERY = "INSERT INTO REGISTRY_ARTIFACT_LOCK(ARTIFACT_NAME, LOCK_COUNT) VALUES (?, 1) 20 | ON DUPLICATE KEY UPDATE LOCK_COUNT = LOCK_COUNT + 1"; 21 | const string DELETE_LOCK_ENTRIES_QUERY = "DELETE FROM REGISTRY_ARTIFACT_LOCK WHERE ARTIFACT_NAME = ?"; 22 | 23 | const string GET_ARTIFACT_IMAGE_ID_QUERY = "SELECT ARTIFACT_IMAGE_ID FROM REGISTRY_ARTIFACT_IMAGE 24 | WHERE ORG_NAME = ? AND IMAGE_NAME = ? FOR UPDATE"; 25 | const string UPDATE_PULL_COUNT_QUERY = "UPDATE REGISTRY_ARTIFACT SET PULL_COUNT = PULL_COUNT + 1, 26 | UPDATED_DATE = UPDATED_DATE WHERE ARTIFACT_IMAGE_ID = ? AND VERSION = ?"; 27 | const string INSERT_ARTIFACT_IMAGE_QUERY = "INSERT INTO REGISTRY_ARTIFACT_IMAGE(ARTIFACT_IMAGE_ID, ORG_NAME, 28 | IMAGE_NAME, FIRST_AUTHOR, VISIBILITY) VALUES (?, ?, ?, ?, ?)"; 29 | 30 | const string GET_ORG_DEFAULT_IMAGE_VISIBILITY_QUERY = "SELECT DEFAULT_IMAGE_VISIBILITY 31 | FROM REGISTRY_ORGANIZATION WHERE ORG_NAME = ? FOR UPDATE"; 32 | 33 | const string GET_ARTIFACT_ID_QUERY = "SELECT ARTIFACT_ID FROM REGISTRY_ARTIFACT 34 | WHERE ARTIFACT_IMAGE_ID = ? AND VERSION = ? FOR UPDATE"; 35 | const string INSERT_REGISTRY_ARTIFACT_QUERY = "INSERT INTO REGISTRY_ARTIFACT(ARTIFACT_ID, ARTIFACT_IMAGE_ID, VERSION, 36 | PUSH_COUNT, LAST_AUTHOR, FIRST_AUTHOR, METADATA, STATEFUL) 37 | VALUES (?, ?, ?, 1, ?, ?, ?, ?)"; 38 | const string UPDATE_REGISTRY_ARTIFACT_QUERY = "UPDATE REGISTRY_ARTIFACT SET PUSH_COUNT = PUSH_COUNT + 1, 39 | LAST_AUTHOR = ?, METADATA = ?, STATEFUL = ? WHERE ARTIFACT_ID = ? 40 | AND VERSION = ?"; 41 | 42 | const string INSERT_REGISTRY_ARTIFACT_LABELS_QUERY = "INSERT INTO REGISTRY_ARTIFACT_LABEL(ARTIFACT_ID, LABEL_KEY, 43 | LABEL_VALUE) VALUES (?, ?, ?)"; 44 | const string DELETE_REGISTRY_ARTIFACT_LABELS_QUERY = "DELETE FROM REGISTRY_ARTIFACT_LABEL WHERE ARTIFACT_ID = ?"; 45 | 46 | const string INSERT_REGISTRY_ARTIFACT_INGRESSES_QUERY = "INSERT INTO REGISTRY_ARTIFACT_INGRESS(ARTIFACT_ID, 47 | INGRESS_TYPE) VALUES (?, ?)"; 48 | const string DELETE_REGISTRY_ARTIFACT_INGRESSES_QUERY = "DELETE FROM REGISTRY_ARTIFACT_INGRESS WHERE ARTIFACT_ID = ?"; 49 | -------------------------------------------------------------------------------- /components/portal/src/utils/api/authUtils.test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | /* eslint camelcase: ["off"] */ 20 | 21 | import AuthUtils from "./authUtils"; 22 | import HttpUtils from "./httpUtils"; 23 | import {StateHolder} from "../../components/common/state"; 24 | 25 | describe("AuthUtils", () => { 26 | const username = "User1"; 27 | const loggedInUser = { 28 | username: username, 29 | tokens: { 30 | accessToken: "12345", 31 | idToken: "54321" 32 | } 33 | }; 34 | afterEach(() => { 35 | localStorage.removeItem(StateHolder.USER); 36 | }); 37 | 38 | describe("updateUser()", () => { 39 | it("should set the username provided", () => { 40 | const stateHolder = new StateHolder(); 41 | const spy = jest.spyOn(stateHolder, "set"); 42 | AuthUtils.updateUser(loggedInUser, stateHolder); 43 | 44 | expect(spy).toHaveBeenCalledTimes(1); 45 | expect(spy).toHaveBeenCalledWith(StateHolder.USER, loggedInUser); 46 | expect(localStorage.getItem(StateHolder.USER)).toBe(JSON.stringify(loggedInUser)); 47 | }); 48 | }); 49 | 50 | describe("signOut()", () => { 51 | it("should unset the user in the state", async () => { 52 | const stateHolder = new StateHolder(); 53 | localStorage.setItem(StateHolder.USER, JSON.stringify(loggedInUser)); 54 | stateHolder.state[StateHolder.USER] = { 55 | value: {...loggedInUser}, 56 | listeners: [] 57 | }; 58 | stateHolder.state[StateHolder.CONFIG] = { 59 | value: { 60 | hubApiUrl: "http://api.hub.cellery.io", 61 | idp: { 62 | url: "https://idp.hub.cellery.io", 63 | clientId: "testclientid" 64 | } 65 | }, 66 | listener: [] 67 | }; 68 | jest.spyOn(window.location, "assign").mockImplementation((location) => { 69 | const params = { 70 | id_token_hint: "54321", 71 | post_logout_redirect_uri: `${window.location.origin}/` 72 | }; 73 | const endpoint = `${stateHolder.get(StateHolder.CONFIG).idp.url}${AuthUtils.LOGOUT_ENDPOINT}`; 74 | expect(location).toEqual(`${endpoint}${HttpUtils.generateQueryParamString(params)}`); 75 | }); 76 | await AuthUtils.signOut(stateHolder); 77 | expect(localStorage.getItem(StateHolder.USER)).toBeNull(); 78 | window.location.assign.mockClear(); 79 | }); 80 | }); 81 | 82 | describe("getAuthenticatedUser()", () => { 83 | localStorage.setItem(StateHolder.USER, JSON.stringify(loggedInUser)); 84 | const user = AuthUtils.getAuthenticatedUser(); 85 | 86 | expect(user).toEqual({...user}); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /components/docker-auth/cmd/authn/authentication.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package main 20 | 21 | import ( 22 | "fmt" 23 | "strconv" 24 | "strings" 25 | 26 | "github.com/cesanta/docker_auth/auth_server/api" 27 | "go.uber.org/zap" 28 | 29 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/auth" 30 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/extension" 31 | ) 32 | 33 | var logger *zap.SugaredLogger 34 | 35 | type PluginAuthn struct { 36 | } 37 | 38 | func (*PluginAuthn) Authenticate(user string, password api.PasswordString) (bool, api.Labels, error) { 39 | if logger == nil { 40 | logger = extension.NewLogger() 41 | } 42 | return doAuthentication(user, string(password), logger) 43 | } 44 | 45 | func (*PluginAuthn) Stop() { 46 | } 47 | 48 | func (*PluginAuthn) Name() string { 49 | return "plugin auth" 50 | } 51 | 52 | var Authn PluginAuthn 53 | 54 | func doAuthentication(user, incomingToken string, logger *zap.SugaredLogger) (bool, api.Labels, error) { 55 | execId, err := extension.GetExecID(logger) 56 | if err != nil { 57 | return false, nil, fmt.Errorf("error in generating the execId : %s", err) 58 | } 59 | 60 | logger.Debugf("[%s] Username %q and password received from CLI", execId, user) 61 | 62 | tokenArray := strings.Split(incomingToken, ":") 63 | token := tokenArray[0] 64 | 65 | isPing := len(tokenArray) > 1 && tokenArray[1] == "ping" 66 | if isPing { 67 | logger.Debugf("[%s] Ping request received", execId) 68 | } 69 | 70 | // This logic is to allow users to pull public images without credentials. So that only if credentials are 71 | // present, IDP is called. If credentials are not present, through authorization logic image visibility 72 | // will be evaluated. 73 | var isAuthenticated bool 74 | if user != "" && token != "" { 75 | isAuthenticated, err = auth.Authenticate(user, token, logger, execId) 76 | if err != nil { 77 | return false, nil, fmt.Errorf("error while authenticating %v", err) 78 | } 79 | } 80 | if !isAuthenticated { 81 | logger.Debugf("[%s] User access token failed to authenticate. Evaluating ping", execId) 82 | if isPing { 83 | return false, nil, fmt.Errorf("since this is a ping request, exiting with auth fail status " + 84 | "without passing to authorization filter") 85 | } else { 86 | logger.Debugf("[%s] Failed authentication. But passing to authorization filter", execId) 87 | return true, makeAuthenticationLabel(false), nil 88 | } 89 | } else { 90 | logger.Debugf("[%s] User successfully authenticated by validating token", execId) 91 | return true, makeAuthenticationLabel(true), nil 92 | } 93 | } 94 | 95 | func makeAuthenticationLabel(isAuthenticated bool) api.Labels { 96 | authResultString := strconv.FormatBool(isAuthenticated) 97 | authLabels := api.Labels{} 98 | authLabels["isAuthSuccess"] = []string{authResultString} 99 | return authLabels 100 | } 101 | -------------------------------------------------------------------------------- /components/portal/src/components/sdk/SignInSuccess.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import CelleryCmd from "../../img/celleryCmd.png"; 20 | import CheckCircleOutline from "@material-ui/icons/CheckCircleOutlineRounded"; 21 | import Grid from "@material-ui/core/Grid"; 22 | import Link from "@material-ui/core/Link"; 23 | import React from "react"; 24 | import Typography from "@material-ui/core/Typography"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import withGlobalState, {StateHolder} from "../common/state"; 27 | import * as PropTypes from "prop-types"; 28 | 29 | const styles = (theme) => ({ 30 | content: { 31 | paddingTop: theme.spacing(4) 32 | }, 33 | success: { 34 | paddingTop: theme.spacing(2), 35 | paddingBottom: theme.spacing(4) 36 | }, 37 | gotoHub: { 38 | fontWeight: 400, 39 | paddingTop: theme.spacing(2), 40 | color: "#464646", 41 | textAlign: "center" 42 | }, 43 | hubUrl: { 44 | color: "#464646", 45 | textDecoration: "underline" 46 | }, 47 | celleryCmd: { 48 | height: 85, 49 | paddingTop: theme.spacing(2) 50 | }, 51 | check: { 52 | paddingTop: theme.spacing(2), 53 | color: theme.palette.primary.main, 54 | fontSize: "3.3rem" 55 | }, 56 | nextTitle: { 57 | color: "#464646" 58 | } 59 | }); 60 | 61 | const SignInSuccess = (props) => { 62 | const {classes, globalState} = props; 63 | const hubPublicUrl = globalState.get(StateHolder.CONFIG).hubPublicUrl; 64 | return ( 65 |
66 | 67 | 68 | 69 | You are now authenticated with Cellery SDK! 70 | 71 | What's next? 72 | {"Cellery 73 |
74 | You may close this window and go back to your terminal to push your Cell images 75 | 76 | or 77 | You can go to  78 | Cellery Hub to manage your organizations and Cell images. 79 | 80 |
81 | 82 |
83 |
84 | ); 85 | }; 86 | 87 | SignInSuccess.propTypes = { 88 | classes: PropTypes.object.isRequired, 89 | globalState: PropTypes.instanceOf(StateHolder).isRequired 90 | }; 91 | 92 | export default withStyles(styles)(withGlobalState(SignInSuccess)); 93 | -------------------------------------------------------------------------------- /components/api/constants/constants.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | public const string APPLICATION_URL_ENCODED_CONTENT_TYPE = "application/x-www-form-urlencoded"; 20 | 21 | public const string AUTHENTICATED_USER = "x-cellery-hub-user"; 22 | public const string CONSTRUCTED_TOKEN = "x-cellery-hub-user-token"; 23 | public const string G_CAPTCHA_RESPONSE = "g-recaptcha-response"; 24 | public const string SET_COOKIE_HEADER = "Set-Cookie"; 25 | 26 | public const int API_ERROR_CODE = 1; 27 | public const int ENTRY_ALREADY_EXISTING_ERROR_CODE = 2; 28 | public const int ALLOWED_LIMIT_EXCEEDED_ERROR_CODE = 3; 29 | public const int ENTRY_NOT_FOUND_ERROR_CODE = 4; 30 | public const int ACTION_NOT_ALLOWED_ERROR_CODE = 5; 31 | 32 | public const string VALIDATE_USER = "validateUser"; 33 | public const string OFFSET = "offset"; 34 | public const string RESULT_LIMIT = "resultLimit"; 35 | public const string ARTIFACT_VERSION = "artifactVersion"; 36 | public const string ORG_NAME = "orgName"; 37 | public const string IMAGE_NAME = "imageName"; 38 | public const string ORDER_BY = "orderBy"; 39 | 40 | public const string IDP_ENDPOINT_VAR = "idp.endpoint"; 41 | public const string IDP_INTROSPCET_VAR = "idp.introspection.endpoint"; 42 | public const string IDP_USERNAME_VAR = "idp.username"; 43 | public const string IDP_PASSWORD_VAR = "idp.password"; 44 | 45 | public const string DEFAULT_IDP_ENDPOINT = "https://localhost:9443/oauth2/introspect"; 46 | public const string IDP_DEFAULT_PASSWORD = "admin"; 47 | public const string IDP_DEFAULT_USERNAME = "admin"; 48 | 49 | public const string AUTHORIZATION_HEADER = "Authorization"; 50 | public const string COOKIE_HEADER = "Cookie"; 51 | public const string BEARER_HEADER = "Bearer"; 52 | public const string TOKEN_COOKIE_KEY = "chpat"; 53 | 54 | public const string ROLE_ADMIN = "admin"; 55 | public const string ROLE_PUSH = "push"; 56 | public const string DEFAULT_IMAGE_VISIBILITY = "PUBLIC"; 57 | public const string PULL_COUNT = "PULL_COUNT"; 58 | public const string UPDATED_DATE = "UPDATED_DATE"; 59 | 60 | public const string DELETE_ACTION = "delete"; 61 | public const string PULL_ACTION = "pull"; 62 | 63 | public const string TOKEN_CACHE_EXPIRY_VAR = "token.cache.expiry"; 64 | public const string TOKEN_CACHE_CAPACITY_VAR = "token.cache.capacity"; 65 | public const string USERINFO_CACHE_EXPIRY_VAR = "userinfo.cache.expiry"; 66 | public const string USERINFO_CACHE_CAPACITY_VAR = "userinfo.cache.capacity"; 67 | 68 | public const string DOCKER_REGISTRY_SERVICE_NAME = "Docker registry"; 69 | public const string DOCKER_REGISTRY_REPOSITORIES_FILEPATH = "/var/lib/registry/docker/registry/v2/repositories"; 70 | public const string REGISTRY_RESPONSE_ERRORS_FIELD = "errors"; 71 | public const string REGISTRY_RESPONSE_DETAIL_FIELD = "detail"; 72 | public const string REGISTRY_RESPONSE_TYPE_FIELD = "Type"; 73 | public const string REGISTRY_RESPONSE_NAME_FIELD = "Name"; 74 | public const string REGISTRY_RESPONSE_ACTION_FIELD = "Action"; 75 | public const string REGISTRY_DIGEST_HEADER = "Docker-Content-Digest"; 76 | -------------------------------------------------------------------------------- /components/docker-auth/pkg/db/connection.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 WSO2 Inc. (http:www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http:www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package db 20 | 21 | import ( 22 | "database/sql" 23 | "fmt" 24 | "os" 25 | "strconv" 26 | "time" 27 | 28 | _ "github.com/go-sql-driver/mysql" 29 | "go.uber.org/zap" 30 | 31 | "github.com/cellery-io/cellery-hub/components/docker-auth/pkg/extension" 32 | ) 33 | 34 | func GetDbConnectionPool(logger *zap.SugaredLogger) (*sql.DB, error) { 35 | dbDriver := extension.MysqlDriver 36 | dbUser := os.Getenv(extension.MysqlUserEnvVar) 37 | dbPass := os.Getenv(extension.MysqlPasswordEnvVar) 38 | dbName := extension.DbName 39 | host := os.Getenv(extension.MysqlHostEnvVar) 40 | port := os.Getenv(extension.MysqlPortEnvVar) 41 | dbPoolConfigurations, err := resolvePoolingConfigurations(logger) 42 | if err != nil { 43 | logger.Debugf("No db connection pooling configurations found : %s", err) 44 | return nil, fmt.Errorf("failed to fetch db connection pooling configurations : %v", err) 45 | } 46 | 47 | conn := fmt.Sprint(dbUser, ":", dbPass, "@tcp(", host, ":", port, ")/"+dbName) 48 | logger.Debugf("Creating a new db connection pool: %v", conn) 49 | 50 | dbConnection, err := sql.Open(dbDriver, conn) 51 | 52 | if err != nil { 53 | return nil, fmt.Errorf("error occurred while establishing database connection pool "+ 54 | " : %v", err) 55 | } 56 | 57 | dbConnection.SetMaxOpenConns(dbPoolConfigurations[extension.MaxIdleConnectionsEnvVar]) 58 | dbConnection.SetMaxIdleConns(dbPoolConfigurations[extension.ConnectionMaxLifetimeEnvVar]) 59 | dbConnection.SetConnMaxLifetime(time.Minute * time.Duration(dbPoolConfigurations[extension. 60 | ConnectionMaxLifetimeEnvVar])) 61 | 62 | err = dbConnection.Ping() 63 | if err != nil { 64 | return nil, fmt.Errorf("error occurred while pinging database connection pool "+ 65 | " : %v", err) 66 | } 67 | 68 | logger.Debugf("Ping successful. DB connection pool established") 69 | 70 | return dbConnection, nil 71 | } 72 | 73 | func resolvePoolingConfigurations(logger *zap.SugaredLogger) (map[string]int, error) { 74 | m := make(map[string]int) 75 | 76 | maxOpenConnections, err := strconv.Atoi(os.Getenv(extension.MaxOpenConnectionsEnvVar)) 77 | if err != nil { 78 | return nil, fmt.Errorf("error occurred while converting max open connections string into integer "+ 79 | " : %v", err) 80 | } 81 | m[extension.MaxOpenConnectionsEnvVar] = maxOpenConnections 82 | maxIdleConnections, err := strconv.Atoi(os.Getenv(extension.MaxIdleConnectionsEnvVar)) 83 | if err != nil { 84 | return nil, fmt.Errorf("error occurred while converting max idle connections string into integer "+ 85 | " : %v", err) 86 | } 87 | m[extension.MaxIdleConnectionsEnvVar] = maxIdleConnections 88 | maxLifetime, err := strconv.Atoi(os.Getenv(extension.ConnectionMaxLifetimeEnvVar)) 89 | if err != nil { 90 | return nil, fmt.Errorf("error occurred while converting max lifetime string into integer "+ 91 | " : %v", err) 92 | } 93 | m[extension.ConnectionMaxLifetimeEnvVar] = maxLifetime 94 | logger.Debugf("Fetched db connection pooling configurations. MaxOpenConns = %d, "+ 95 | "MaxIdleConns = %d, MaxLifetime = %d", maxOpenConnections, maxIdleConnections, maxLifetime) 96 | 97 | return m, nil 98 | } 99 | -------------------------------------------------------------------------------- /components/api/docker_registry/registry.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/config; 20 | import ballerina/http; 21 | import ballerina/io; 22 | import ballerina/log; 23 | 24 | public function getManifestDigest(string orgName, string imageName, string artifactVersion, string bearerToken) 25 | returns string | error { 26 | log:printDebug(io:sprintf("Invoking getManifest end point of registry API with a docker auth token. orgName: %s, "+ 27 | "imageName: %s, artifactVersion: %s", orgName, imageName, artifactVersion)); 28 | string getManifestEndPoint = io:sprintf("/v2/%s/%s/manifests/%s", orgName, imageName, artifactVersion); 29 | http:Client dockerRegistryClient = getOAuth2RegistryClient(bearerToken); 30 | var responseForGetManifest = dockerRegistryClient->get(getManifestEndPoint, message = ""); 31 | 32 | if (responseForGetManifest is http:Response) { 33 | log:printDebug(io:sprintf("Received status code for getManifestDigest request: %d", 34 | responseForGetManifest.statusCode)); 35 | if (responseForGetManifest.statusCode == http:OK_200) { 36 | log:printDebug(io:sprintf("Successfully retrieved the digest of the atifact \'%s/%s:%s\'. ", orgName, 37 | imageName, artifactVersion)); 38 | return responseForGetManifest.getHeader(constants:REGISTRY_DIGEST_HEADER); 39 | } else { 40 | error er = error(io:sprintf("Failed to fetch the digest of docker manifest. This may be due to an unknown "+ 41 | "manifest. Status Code : %s", responseForGetManifest.statusCode)); 42 | return er; 43 | } 44 | } else { 45 | error er = error(io:sprintf("Error while fetching digest of docker manifest. %s", responseForGetManifest)); 46 | return er; 47 | } 48 | } 49 | 50 | public function deleteManifest(string orgName, string imageName, string manifestdigest, string bearerToken) 51 | returns error? { 52 | log:printDebug(io:sprintf("Invoking deleteManifest end point of registry API with a docker auth token. orgName: %s, "+ 53 | "imageName: %s, digest: %s", orgName, imageName, manifestdigest)); 54 | http:Client dockerRegistryClient = getOAuth2RegistryClient(bearerToken); 55 | string deleteEndPoint = io:sprintf("/v2/%s/%s/manifests/%s", orgName, imageName, manifestdigest); 56 | var responseForDeleteManifest = dockerRegistryClient->delete(deleteEndPoint, ""); 57 | 58 | if (responseForDeleteManifest is http:Response) { 59 | log:printDebug(io:sprintf("Received status code for deleteManifes request: %d", 60 | responseForDeleteManifest.statusCode)); 61 | if (responseForDeleteManifest.statusCode == http:ACCEPTED_202) { 62 | log:printDebug(io:sprintf("Deleted the artifact \'%s/%s\'. Digest : %s", orgName, imageName, 63 | manifestdigest)); 64 | } else { 65 | error er = error("Failed to delete the docker manifest. This may be due to an unknown manifest"); 66 | return er; 67 | } 68 | } else { 69 | error er = error(io:sprintf("Error while deleting docker manifest. %s", responseForDeleteManifest)); 70 | return er; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /components/portal/src/components/common/error/UnknownError.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Button from "@material-ui/core/Button/Button"; 20 | import CelleryError from "../../../img/celleryError.jpg"; 21 | import Home from "@material-ui/icons/Home"; 22 | import React from "react"; 23 | import {withRouter} from "react-router-dom"; 24 | import {withStyles} from "@material-ui/core"; 25 | import * as PropTypes from "prop-types"; 26 | 27 | const styles = (theme) => ({ 28 | unknownErrorContainer: { 29 | position: "relative", 30 | top: 0, 31 | left: 0, 32 | height: "100%", 33 | width: "100%", 34 | display: "grid" 35 | }, 36 | unknownError: { 37 | margin: "auto", 38 | textAlign: "center" 39 | }, 40 | unknownErrorImg: { 41 | marginTop: theme.spacing.unit * 5, 42 | height: 150 43 | }, 44 | unknownErrorTitle: { 45 | margin: theme.spacing.unit, 46 | fontSize: "1.5em", 47 | fontWeight: 400, 48 | color: "#6e6e6e" 49 | }, 50 | unknownErrorDescription: { 51 | fontSize: "1em", 52 | fontWeight: 300, 53 | color: "#808080", 54 | maxWidth: "50vw" 55 | }, 56 | navigationButtonsContainer: { 57 | margin: theme.spacing.unit * 3 58 | }, 59 | navigationButton: { 60 | margin: theme.spacing.unit 61 | }, 62 | navigationButtonIcon: { 63 | marginRight: theme.spacing.unit 64 | } 65 | }); 66 | 67 | const UnknownError = ({classes, title, description, showNavigationButtons}) => ( 68 |
69 |
70 | {"Unknown 71 |
72 | {title ? title : "Something Went Wrong"} 73 |
74 | { 75 | description 76 | ? ( 77 |
78 | {description} 79 |
80 | ) 81 | : null 82 | } 83 | { 84 | showNavigationButtons 85 | ? ( 86 |
87 | 92 |
93 | ) 94 | : null 95 | } 96 |
97 |
98 | ); 99 | 100 | UnknownError.propTypes = { 101 | classes: PropTypes.object.isRequired, 102 | title: PropTypes.string, 103 | description: PropTypes.string, 104 | showNavigationButtons: PropTypes.bool 105 | }; 106 | 107 | export default withStyles(styles, {withTheme: true})(withRouter(UnknownError)); 108 | -------------------------------------------------------------------------------- /components/api/idp/validator.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/config; 20 | import ballerina/http; 21 | import ballerina/log; 22 | import ballerina/time; 23 | import ballerina/io; 24 | 25 | public type TokenDetail record { 26 | string username; 27 | int expiryTime; 28 | int storedTime; 29 | }; 30 | 31 | # This is used to validate the token comming in and returning token detail consists of expiry time and username 32 | # + token - access token to be validated 33 | # + return - returns a token detail if an access token is valid otherwise retuns a error 34 | public function getTokenDetails(string token) returns (TokenDetail)|error { 35 | log:printDebug("Access token validator reached and token will be validated"); 36 | http:Request req = new; 37 | req.setPayload(io:sprintf("token=" + token)); 38 | error ? x = req.setContentType(constants:APPLICATION_URL_ENCODED_CONTENT_TYPE); 39 | // TODO There is a bug on ballerina that when there are more than one global client endpoints, 40 | // we have to reinitialize the endpoint. Need to remove this after the bug on this in ballerina is fixed 41 | http:Client idpClientEP = getBasicAuthIDPClient(config:getAsString("idp.username"),config:getAsString("idp.password")); 42 | var response = idpClientEP->post(config:getAsString(constants:IDP_INTROSPCET_VAR), req); 43 | if (response is http:Response) { 44 | if (response.statusCode < 200 || response.statusCode > 300){ 45 | log:printError("Failed to call introspection endpoint with status code " + response.statusCode); 46 | error err = error("Failed to call introspection endpoint with status code " + response.statusCode); 47 | return err; 48 | } 49 | json result = check response.getJsonPayload(); 50 | log:printDebug(io:sprintf("Response json from the introspection endpoint is %s", check string.convert(result))); 51 | var isValid = check boolean.convert(result.active); 52 | var fullyQualifiedUsername = check string.convert(result.username); 53 | TokenDetail tokenDetail = { 54 | username: fullyQualifiedUsername.split("@")[0], 55 | expiryTime: check int.convert(result.exp), 56 | storedTime: time:currentTime().time 57 | }; 58 | if (isValid) { 59 | if (tokenDetail.username != "") || (tokenDetail.expiryTime == 0) { 60 | return tokenDetail; 61 | } else { 62 | log:printError("Provided username does not match with the username in the token"); 63 | UsernameNotFoundErrorData errorDetail = { 64 | errUsername: tokenDetail.username 65 | }; 66 | UsernameNotFoundError userNotFoundError = 67 | error("Provided username does not match with the username in the token", errorDetail); 68 | return userNotFoundError; 69 | } 70 | } 71 | log:printError("Token is not active"); 72 | return tokenDetail; 73 | } else { 74 | log:printError("Failed to call the introspection endpoint", err = response); 75 | return response; 76 | } 77 | } 78 | 79 | type UsernameNotFoundErrorData record { 80 | string errUsername; 81 | }; 82 | 83 | type UsernameNotFoundError error; 84 | -------------------------------------------------------------------------------- /components/portal/src/components/sdk/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import AppLayout from "./appLayout"; 20 | import ErrorBoundary from "../common/error/ErrorBoundary"; 21 | import NotFound from "../common/error/NotFound"; 22 | import OrgCreate from "./OrgCreate"; 23 | import React from "react"; 24 | import SignIn from "./SignIn"; 25 | import SignInFailure from "./SignInFailure"; 26 | import SignInRequired from "../common/error/SignInRequired"; 27 | import SignInSuccess from "./SignInSuccess"; 28 | import {withStyles} from "@material-ui/core/styles"; 29 | import {Route, Switch} from "react-router-dom"; 30 | import withGlobalState, {StateHolder} from "../common/state"; 31 | import * as PropTypes from "prop-types"; 32 | 33 | class StatelessProtectedSDKPortal extends React.Component { 34 | 35 | constructor(props) { 36 | super(props); 37 | this.state = { 38 | user: props.globalState.get(StateHolder.USER) 39 | }; 40 | props.globalState.addListener(StateHolder.USER, this.handleUserChange); 41 | } 42 | 43 | handleUserChange = (key, oldValue, newValue) => { 44 | this.setState({ 45 | user: newValue 46 | }); 47 | }; 48 | 49 | render = () => { 50 | const {match} = this.props; 51 | const {user} = this.state; 52 | let view; 53 | if (user) { 54 | view = ( 55 | 56 | 57 | 58 | 59 | }/> 60 | 61 | ); 62 | } else { 63 | view = ; 64 | } 65 | return view; 66 | } 67 | 68 | } 69 | 70 | StatelessProtectedSDKPortal.propTypes = { 71 | match: PropTypes.shape({ 72 | url: PropTypes.string.isRequired 73 | }).isRequired, 74 | globalState: PropTypes.instanceOf(StateHolder) 75 | }; 76 | 77 | const ProtectedSDKPortal = withGlobalState(StatelessProtectedSDKPortal); 78 | 79 | const styles = () => ({ 80 | centerContainer: { 81 | position: "absolute", 82 | margin: "auto", 83 | top: 0, 84 | right: 0, 85 | bottom: 0, 86 | left: 0, 87 | width: "200px", 88 | height: "100px", 89 | verticalAlign: "middle" 90 | } 91 | }); 92 | 93 | const SDK = ({match}) => ( 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | ); 103 | 104 | SDK.propTypes = { 105 | classes: PropTypes.object.isRequired, 106 | location: PropTypes.shape({ 107 | pathname: PropTypes.string.isRequired, 108 | search: PropTypes.object.isRequired 109 | }).isRequired, 110 | history: PropTypes.shape({ 111 | replace: PropTypes.func.isRequired 112 | }).isRequired, 113 | match: PropTypes.shape({ 114 | url: PropTypes.string.isRequired 115 | }).isRequired 116 | }; 117 | 118 | export default withStyles(styles)(SDK); 119 | -------------------------------------------------------------------------------- /components/portal/src/components/appLayout/Footer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import CelleryLogo from "../../img/celleryLogo.svg"; 20 | import Container from "@material-ui/core/Container"; 21 | import Link from "@material-ui/core/Link"; 22 | import React from "react"; 23 | import Typography from "@material-ui/core/Typography"; 24 | import {withRouter} from "react-router-dom"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import * as PropTypes from "prop-types"; 27 | 28 | const styles = (theme) => ({ 29 | footerContent: { 30 | backgroundColor: "#e5eaea", 31 | color: "#57595d", 32 | height: 70, 33 | display: "flex", 34 | alignItems: "center" 35 | }, 36 | footerLink: { 37 | textTransform: "uppercase", 38 | color: "#57595d", 39 | letterSpacing: 1, 40 | fontWeight: 500, 41 | textDecoration: "none", 42 | "&:hover": { 43 | textDecoration: "none" 44 | }, 45 | fontSize: 11 46 | }, 47 | footerLinkCompany: { 48 | textTransform: "uppercase", 49 | color: "#57595d", 50 | letterSpacing: 1, 51 | fontWeight: 500, 52 | textDecoration: "none", 53 | "&:hover": { 54 | textDecoration: "none" 55 | } 56 | }, 57 | title: { 58 | flexGrow: 1 59 | }, 60 | copyRightInfo: { 61 | display: "flex" 62 | }, 63 | celleryLogoFooter: { 64 | height: 20, 65 | verticalAlign: "middle" 66 | }, 67 | separator: { 68 | paddingLeft: theme.spacing(2), 69 | paddingRight: theme.spacing(2), 70 | color: "#c3c6cc" 71 | } 72 | }); 73 | 74 | const Footer = (props) => { 75 | const {classes} = props; 76 | 77 | return ( 78 |
79 |
80 | 81 |
82 | 83 | © 2019 84 | WSO2 86 | 87 | 88 | Terms of Service 89 | | 90 | 91 | Privacy Policy 92 | | 93 | 94 | Cookie Policy 95 |
96 | 97 | {"Cellery 98 | 99 |
100 |
101 |
102 | ); 103 | }; 104 | 105 | Footer.propTypes = { 106 | classes: PropTypes.object.isRequired 107 | }; 108 | 109 | export default withStyles(styles)(withRouter(Footer)); 110 | -------------------------------------------------------------------------------- /components/portal/src/img/celleryLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 28 | 29 | 33 | 35 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /docker/identity-server/resources/authenticationendpoint/cellery_error.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | ~ Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | ~ 4 | ~ WSO2 Inc. licenses this file to you under the Apache License, 5 | ~ Version 2.0 (the "License"); you may not use this file except 6 | ~ in compliance with the License. 7 | ~ You may obtain a copy of the License at 8 | ~ 9 | ~ http://www.apache.org/licenses/LICENSE-2.0 10 | ~ 11 | ~ Unless required by applicable law or agreed to in writing, 12 | ~ software distributed under the License is distributed on an 13 | ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | ~ KIND, either express or implied. See the License for the 15 | ~ specific language governing permissions and limitations 16 | ~ under the License. 17 | --%> 18 | 19 | <%@ page import="org.owasp.encoder.Encode" %> 20 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> 21 | <%@include file="localize.jsp" %> 22 | 23 | 24 | 25 | 26 | 27 | 28 | <%=AuthenticationEndpointUtil.i18n(resourceBundle, "business.name")%> 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | 53 |
54 | 55 | 56 |
57 |
58 | 59 |
60 |
61 | 62 |
63 |

<%=AuthenticationEndpointUtil.i18n(resourceBundle, "something.went.wrong")%>

64 |

<%=AuthenticationEndpointUtil.i18n(resourceBundle, "sign.in.again")%>

65 |
66 |
67 | 69 |
70 |
71 |
72 | 73 |
74 |
75 | 76 | 77 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /components/portal/src/components/common/error/NotFound.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import ArrowBack from "@material-ui/icons/ArrowBack"; 20 | import Button from "@material-ui/core/Button/Button"; 21 | import CelleryError from "../../../img/celleryError.jpg"; 22 | import Home from "@material-ui/icons/Home"; 23 | import React from "react"; 24 | import {withRouter} from "react-router-dom"; 25 | import {withStyles} from "@material-ui/core"; 26 | import * as PropTypes from "prop-types"; 27 | 28 | const styles = (theme) => ({ 29 | notFoundContainer: { 30 | position: "relative", 31 | top: 0, 32 | left: 0, 33 | height: "100%", 34 | width: "100%", 35 | display: "grid" 36 | }, 37 | notFound: { 38 | margin: "auto", 39 | textAlign: "center" 40 | }, 41 | notFoundImg: { 42 | marginTop: theme.spacing.unit * 5, 43 | height: 150 44 | }, 45 | notFoundTitle: { 46 | margin: theme.spacing.unit, 47 | fontSize: "1.5em", 48 | fontWeight: 400, 49 | color: "#6e6e6e" 50 | }, 51 | notFoundDescription: { 52 | fontSize: "1em", 53 | fontWeight: 300, 54 | color: "#808080", 55 | maxWidth: "50vw" 56 | }, 57 | navigationButton: { 58 | margin: theme.spacing.unit 59 | }, 60 | navigationButtonIcon: { 61 | marginRight: theme.spacing.unit 62 | } 63 | }); 64 | 65 | const NotFound = ({classes, history, title, description, showNavigationButtons}) => ( 66 |
67 |
68 | {"Not 69 |
70 | {title ? title : "Unable to Find What You were Looking for"} 71 |
72 | { 73 | description 74 | ? ( 75 |
76 | {description} 77 |
78 | ) 79 | : null 80 | } 81 | { 82 | showNavigationButtons 83 | ? ( 84 | 85 | 90 | 95 | 96 | ) 97 | : null 98 | } 99 |
100 |
101 | ); 102 | 103 | NotFound.propTypes = { 104 | classes: PropTypes.object.isRequired, 105 | history: PropTypes.shape({ 106 | goBack: PropTypes.func.isRequired, 107 | push: PropTypes.func.isRequired 108 | }), 109 | title: PropTypes.string, 110 | description: PropTypes.string, 111 | showNavigationButtons: PropTypes.bool 112 | }; 113 | 114 | export default withStyles(styles, {withTheme: true})(withRouter(NotFound)); 115 | -------------------------------------------------------------------------------- /components/api/idp/user_info_retriver.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | import ballerina/http; 20 | import ballerina/log; 21 | import ballerina/cache; 22 | 23 | public type UserInfo record { 24 | string userId; 25 | string firstName; 26 | string lastName; 27 | string displayName; 28 | string email; 29 | }; 30 | 31 | int userInfoCacheExpiryTime = config:getAsInt(constants:USERINFO_CACHE_EXPIRY_VAR, defaultValue = 1800000); 32 | cache:Cache userInfoCache = new(capacity = config:getAsInt(constants:USERINFO_CACHE_CAPACITY_VAR, defaultValue = 500), 33 | expiryTimeMillis = userInfoCacheExpiryTime); 34 | 35 | public function getUserInfo(string userId) returns UserInfo? | error { 36 | 37 | log:printDebug(io:sprintf("Retrieving userInformation organizations for user : \'%s\'", userId)); 38 | if(userInfoCache.hasKey(userId)) { 39 | log:printDebug(io:sprintf("Found cached userinfo for user : \'%s\'", userId)); 40 | return userInfoCache.get(userId); 41 | } 42 | // TODO There is a bug on ballerina that when there are more than one global client endpoints, 43 | // we have to reinitialize the endpoint. Need to remove this after the bug on this in ballerina is fixed 44 | log:printDebug(io:sprintf("User info not found in cache for user : \'%s\'. Hence calling IDP", userId)); 45 | http:Client idpClientEP = getBasicAuthIDPClient(config:getAsString("idp.username"),config:getAsString("idp.password")); 46 | var response = check idpClientEP->get(config:getAsString("idp.scim2.user.endpoint") + 47 | "?filter=username+eq+" + userId); 48 | 49 | 50 | if (response.statusCode >= 300) { 51 | error err = error(io:sprintf("Failed to call IdP scim endpoint. Recieved status code ", response.statusCode)); 52 | return err; 53 | } 54 | 55 | json scimUserFilterResponse = check response.getJsonPayload(); 56 | log:printDebug("Response from user info request to IDP : " +check string.convert(scimUserFilterResponse)); 57 | if (scimUserFilterResponse.totalResults == 0) { 58 | log:printDebug(io:sprintf("No users found with given Id : \'%s\'", userId)); 59 | return; 60 | } else if (scimUserFilterResponse.totalResults == 1) { 61 | json userResource = scimUserFilterResponse.Resources[0]; 62 | string username = ""; 63 | string firstName = ""; 64 | string lastName = ""; 65 | string displayName = ""; 66 | string email = "email"; 67 | if (userResource.userName != ()) { 68 | username = userResource.userName; 69 | } 70 | if (userResource.name != ()) { 71 | if (userResource.name.givenName != ()) { 72 | firstName = userResource.name.givenName; 73 | } 74 | if (userResource.name.familyName != ()) { 75 | lastName = userResource.name.familyName; 76 | } 77 | } 78 | if (userResource.displayName != ()) { 79 | displayName = userResource.displayName; 80 | } 81 | if (userResource.emails != () && userResource.emails.length() > 0) { 82 | email = userResource.emails[0]; 83 | } 84 | UserInfo userInfo = { 85 | userId: username, 86 | firstName: firstName, 87 | lastName: lastName, 88 | displayName: displayName, 89 | email: email 90 | }; 91 | log:printDebug("Returning user info recieved from IDP"); 92 | userInfoCache.put(userId, userInfo); 93 | return userInfo; 94 | } 95 | log:printDebug(io:sprintf("More than 1 user found for the given user ID hence not returning user info for user 96 | : \'%s\'", userId)); 97 | return; 98 | } 99 | -------------------------------------------------------------------------------- /components/portal/src/components/common/CustomizedTabs.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import HttpUtils from "../../utils/api/httpUtils"; 20 | import React from "react"; 21 | import Tab from "@material-ui/core/Tab"; 22 | import Tabs from "@material-ui/core/Tabs"; 23 | import Typography from "@material-ui/core/Typography"; 24 | import {withRouter} from "react-router-dom"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import * as PropTypes from "prop-types"; 27 | 28 | const CustomTabs = withStyles((theme) => ({ 29 | root: { 30 | borderBottom: "1px solid #e8e8e8" 31 | }, 32 | indicator: { 33 | backgroundColor: theme.palette.primary.main 34 | } 35 | }))(Tabs); 36 | 37 | const CustomTab = withStyles((theme) => ({ 38 | root: { 39 | textTransform: "none", 40 | minWidth: 72, 41 | fontSize: 14, 42 | marginRight: theme.spacing(4), 43 | "&:hover": { 44 | color: "#464646", 45 | opacity: 1 46 | }, 47 | "&$selected": { 48 | color: "#464646", 49 | fontWeight: theme.typography.fontWeightMedium 50 | }, 51 | "&:focus": { 52 | color: "#464646" 53 | } 54 | }, 55 | selected: {} 56 | }))((props) => ); 57 | 58 | const styles = () => ({ 59 | root: { 60 | flexGrow: 1 61 | } 62 | }); 63 | 64 | const TabContainer = ({children}) => ( 65 | 66 | {children} 67 | 68 | ); 69 | 70 | TabContainer.propTypes = { 71 | children: PropTypes.any.isRequired 72 | }; 73 | 74 | class CustomizedTabs extends React.Component { 75 | 76 | handleTabChange = (event, newSelectedIndex) => { 77 | const {history, match, location, tabs, retainCurrentQueryParams} = this.props; 78 | 79 | const queryParamsString = HttpUtils.generateQueryParamString({ 80 | ...(retainCurrentQueryParams ? HttpUtils.parseQueryParams(location.search) : {}), 81 | tab: tabs[newSelectedIndex].label 82 | }); 83 | history.replace(match.url + queryParamsString, retainCurrentQueryParams ? {...location.state} : {}); 84 | }; 85 | 86 | render = () => { 87 | const {classes, location, tabs} = this.props; 88 | 89 | const queryParams = HttpUtils.parseQueryParams(location.search); 90 | const selectedIndex = queryParams.tab ? tabs.findIndex((tab) => tab.label === queryParams.tab) : 0; 91 | return ( 92 |
93 | 94 | { 95 | tabs.map((item) => ( 96 | 97 | )) 98 | } 99 | 100 | { 101 | tabs.map((item, index) => ( 102 | selectedIndex === index && {item.render()} 103 | )) 104 | } 105 |
106 | ); 107 | } 108 | 109 | } 110 | 111 | CustomizedTabs.propTypes = { 112 | history: PropTypes.shape({ 113 | replace: PropTypes.func.isRequired 114 | }).isRequired, 115 | match: PropTypes.shape({ 116 | url: PropTypes.string.isRequired 117 | }).isRequired, 118 | location: PropTypes.shape({ 119 | search: PropTypes.string.isRequired, 120 | state: PropTypes.object.isRequired 121 | }).isRequired, 122 | classes: PropTypes.object.isRequired, 123 | tabs: PropTypes.arrayOf(PropTypes.shape({ 124 | label: PropTypes.string.isRequired, 125 | render: PropTypes.func.isRequired 126 | })).isRequired, 127 | retainCurrentQueryParams: PropTypes.bool 128 | }; 129 | 130 | export default withRouter(withStyles(styles)(CustomizedTabs)); 131 | -------------------------------------------------------------------------------- /components/portal/src/components/SignIn.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import AuthUtils from "../utils/api/authUtils"; 20 | import CircularProgress from "@material-ui/core/CircularProgress"; 21 | import Grid from "@material-ui/core/Grid/Grid"; 22 | import HttpUtils from "../utils/api/httpUtils"; 23 | import React from "react"; 24 | import {withRouter} from "react-router-dom"; 25 | import {withStyles} from "@material-ui/core/styles"; 26 | import withGlobalState, {StateHolder} from "./common/state"; 27 | import * as PropTypes from "prop-types"; 28 | 29 | const styles = (theme) => ({ 30 | layout: { 31 | width: "auto", 32 | display: "block", // Fix IE 11 issue. 33 | marginLeft: theme.spacing.unit * 3, 34 | marginRight: theme.spacing.unit * 3, 35 | [theme.breakpoints.up(400 + (theme.spacing.unit * 3 * 2))]: { 36 | width: 400, 37 | marginLeft: "auto", 38 | marginRight: "auto" 39 | } 40 | }, 41 | paper: { 42 | marginTop: theme.spacing.unit * 8, 43 | display: "flex", 44 | flexDirection: "column", 45 | alignItems: "center", 46 | padding: `${theme.spacing.unit * 2}px ${theme.spacing.unit * 3}px ${theme.spacing.unit * 3}px` 47 | }, 48 | heading: { 49 | margin: theme.spacing.unit, 50 | paddingTop: theme.spacing.unit * 2 51 | }, 52 | form: { 53 | width: "100%", // Fix IE 11 issue. 54 | marginTop: theme.spacing.unit 55 | }, 56 | submit: { 57 | marginTop: theme.spacing.unit * 3 58 | }, 59 | centerContainer: { 60 | position: "absolute", 61 | margin: "auto", 62 | top: 0, 63 | right: 0, 64 | bottom: 0, 65 | left: 0, 66 | width: "200px", 67 | height: "100px" 68 | } 69 | }); 70 | 71 | class SignIn extends React.Component { 72 | 73 | static CALLBACK = "signInComponentCallback"; 74 | 75 | componentDidMount() { 76 | const {defaultCallback, globalState, history, location} = this.props; 77 | const searchParams = HttpUtils.parseQueryParams(location.search); 78 | if (searchParams.code) { 79 | const oneTimeToken = searchParams.code; 80 | AuthUtils.retrieveTokens(oneTimeToken, globalState, () => { 81 | searchParams.code = null; 82 | history.replace(`${location.pathname}${HttpUtils.generateQueryParamString(searchParams)}`); 83 | 84 | if (sessionStorage.getItem(SignIn.CALLBACK)) { 85 | const callback = sessionStorage.getItem(SignIn.CALLBACK); 86 | sessionStorage.removeItem(SignIn.CALLBACK); 87 | history.replace(callback); 88 | } else if (defaultCallback) { 89 | history.replace(defaultCallback); 90 | } 91 | }); 92 | } else { 93 | if (searchParams.callback) { 94 | sessionStorage.setItem(SignIn.CALLBACK, searchParams.callback); 95 | } 96 | AuthUtils.initiateHubLoginFlow(globalState); 97 | } 98 | } 99 | 100 | render() { 101 | const {classes} = this.props; 102 | return ( 103 | 104 | 105 |  Signing In 106 | 107 | ); 108 | } 109 | 110 | } 111 | 112 | SignIn.propTypes = { 113 | classes: PropTypes.object.isRequired, 114 | globalState: PropTypes.instanceOf(StateHolder).isRequired, 115 | location: PropTypes.shape({ 116 | search: PropTypes.string.isRequired 117 | }).isRequired, 118 | history: PropTypes.shape({ 119 | replace: PropTypes.func.isRequired 120 | }), 121 | defaultCallback: PropTypes.string 122 | }; 123 | 124 | export default withRouter(withStyles(styles)(withGlobalState(SignIn))); 125 | -------------------------------------------------------------------------------- /components/identity-server-customization/cellery-identity-customizations/src/main/java/io/cellery/hub/identity/extension/DBPersistanceManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | package io.cellery.hub.identity.extension; 20 | 21 | import org.apache.commons.logging.Log; 22 | import org.apache.commons.logging.LogFactory; 23 | import org.wso2.carbon.identity.base.IdentityException; 24 | import org.wso2.carbon.identity.base.IdentityRuntimeException; 25 | 26 | import java.sql.Connection; 27 | import java.sql.SQLException; 28 | import javax.naming.Context; 29 | import javax.naming.InitialContext; 30 | import javax.naming.NamingException; 31 | import javax.sql.DataSource; 32 | 33 | /** 34 | * DB persistance manager for cellery hub database. 35 | */ 36 | public class DBPersistanceManager { 37 | 38 | private static Log log = LogFactory.getLog(DBPersistanceManager.class); 39 | private static volatile DBPersistanceManager instance; 40 | private DataSource dataSource; 41 | // This property refers to Active transaction state of postgresql db 42 | private static final String PG_ACTIVE_SQL_TRANSACTION_STATE = "25001"; 43 | private static final String POSTGRESQL_DATABASE = "PostgreSQL"; 44 | 45 | private DBPersistanceManager() { 46 | 47 | initDataSource(); 48 | } 49 | 50 | /** 51 | * Get an instance of the JDBCPersistenceManager. It implements a lazy 52 | * initialization with double 53 | * checked locking, because it is initialized first by identity.core module 54 | * during the start up. 55 | * 56 | * @return JDBCPersistenceManager instance 57 | * @throws IdentityException Error when reading the data source configurations 58 | */ 59 | public static DBPersistanceManager getInstance() { 60 | 61 | if (instance == null) { 62 | synchronized (DBPersistanceManager.class) { 63 | if (instance == null) { 64 | instance = new DBPersistanceManager(); 65 | } 66 | } 67 | } 68 | return instance; 69 | } 70 | 71 | private void initDataSource() { 72 | 73 | try { 74 | 75 | String dataSourceName = "jdbc/CELLERY_HUB"; 76 | Context ctx = new InitialContext(); 77 | dataSource = (DataSource) ctx.lookup(dataSourceName); 78 | 79 | } catch (NamingException e) { 80 | String errorMsg = "Error when looking up the Identity Data Source."; 81 | throw IdentityRuntimeException.error(errorMsg, e); 82 | } 83 | } 84 | 85 | /** 86 | * Returns an database connection for Identity data source. 87 | * 88 | * @return Database connection 89 | * @throws IdentityException Exception occurred when getting the data source. 90 | */ 91 | public Connection getDBConnection() throws IdentityRuntimeException { 92 | 93 | try { 94 | Connection dbConnection = dataSource.getConnection(); 95 | dbConnection.setAutoCommit(false); 96 | try { 97 | dbConnection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); 98 | } catch (SQLException e) { 99 | // Handling startup error for postgresql 100 | // Active SQL Transaction means that connection is not committed. 101 | // Need to commit before setting isolation property. 102 | if (dbConnection.getMetaData().getDriverName().contains(POSTGRESQL_DATABASE) && 103 | PG_ACTIVE_SQL_TRANSACTION_STATE.equals(e.getSQLState())) { 104 | dbConnection.commit(); 105 | dbConnection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); 106 | } 107 | } 108 | return dbConnection; 109 | } catch (SQLException e) { 110 | String errMsg = "Error when getting a database connection object from the Identity data source."; 111 | throw IdentityRuntimeException.error(errMsg, e); 112 | } 113 | } 114 | 115 | /** 116 | * Returns Identity data source. 117 | * 118 | * @return data source 119 | */ 120 | public DataSource getDataSource() { 121 | 122 | return dataSource; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /components/portal/src/components/common/error/SignInRequired.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import ArrowBack from "@material-ui/icons/ArrowBack"; 20 | import Button from "@material-ui/core/Button/Button"; 21 | import CelleryError from "../../../img/celleryError.jpg"; 22 | import Home from "@material-ui/icons/Home"; 23 | import React from "react"; 24 | import Typography from "@material-ui/core/Typography"; 25 | import {withRouter} from "react-router-dom"; 26 | import {withStyles} from "@material-ui/core"; 27 | import * as PropTypes from "prop-types"; 28 | 29 | const styles = (theme) => ({ 30 | signInRequiredContainer: { 31 | position: "relative", 32 | top: 0, 33 | left: 0, 34 | height: "100%", 35 | width: "100%", 36 | display: "grid" 37 | }, 38 | signInRequired: { 39 | margin: "auto", 40 | textAlign: "center" 41 | }, 42 | signInRequiredImg: { 43 | marginTop: theme.spacing(5), 44 | height: 150 45 | }, 46 | signInRequiredTitle: { 47 | margin: theme.spacing(1), 48 | fontSize: "1rem", 49 | fontWeight: 400, 50 | color: "#6e6e6e" 51 | }, 52 | signInRequiredDescription: { 53 | fontSize: "1em", 54 | fontWeight: 300, 55 | color: "#808080", 56 | maxWidth: "50vw" 57 | }, 58 | navigationButton: { 59 | margin: theme.spacing(1) 60 | }, 61 | navigationButtonIcon: { 62 | marginRight: theme.spacing(1) 63 | }, 64 | gotoHubButton: { 65 | marginTop: theme.spacing(2), 66 | borderColor: theme.palette.primary.main 67 | } 68 | }); 69 | 70 | const SignInRequired = ({classes, history, title, description, showNavigationButtons}) => ( 71 |
72 |
73 | {"Sign 74 |
75 | {title ? title : "You need to Sign In to view this"} 76 |
77 | { 78 | description 79 | ? ( 80 |
81 | {description} 82 |
83 | ) 84 | : null 85 | } 86 | { 87 | showNavigationButtons 88 | ? ( 89 | 90 | 95 | 100 | 101 | ) 102 | : ( 103 | 104 | 108 | 109 | ) 110 | } 111 |
112 |
113 | ); 114 | 115 | SignInRequired.propTypes = { 116 | classes: PropTypes.object.isRequired, 117 | history: PropTypes.shape({ 118 | goBack: PropTypes.func.isRequired, 119 | push: PropTypes.func.isRequired 120 | }), 121 | title: PropTypes.string, 122 | description: PropTypes.string, 123 | showNavigationButtons: PropTypes.bool 124 | }; 125 | 126 | export default withStyles(styles, {withTheme: true})(withRouter(SignInRequired)); 127 | -------------------------------------------------------------------------------- /components/portal/src/components/org/OrgDeleteDialog.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Button from "@material-ui/core/Button"; 20 | import Dialog from "@material-ui/core/Dialog"; 21 | import DialogActions from "@material-ui/core/DialogActions"; 22 | import DialogContent from "@material-ui/core/DialogContent"; 23 | import DialogContentText from "@material-ui/core/DialogContentText"; 24 | import DialogTitle from "@material-ui/core/DialogTitle"; 25 | import NotificationUtils from "../../utils/common/notificationUtils"; 26 | import React from "react"; 27 | import {withRouter} from "react-router-dom"; 28 | import {withStyles} from "@material-ui/core/styles/index"; 29 | import HttpUtils, {HubApiError} from "../../utils/api/httpUtils"; 30 | import withGlobalState, {StateHolder} from "../common/state"; 31 | import * as PropTypes from "prop-types"; 32 | 33 | const styles = (theme) => ({ 34 | dialogActions: { 35 | marginBottom: theme.spacing(2) 36 | }, 37 | deleteBtn: { 38 | color: "#e74c3c", 39 | borderColor: "#e74c3c", 40 | marginRight: theme.spacing(2) 41 | } 42 | }); 43 | 44 | class OrgDeleteDialog extends React.Component { 45 | 46 | handleDeleteOrg = () => { 47 | const self = this; 48 | const {globalState, org, history} = self.props; 49 | NotificationUtils.showLoadingOverlay(`Deleting organization ${org}`, globalState); 50 | HttpUtils.callHubAPI( 51 | { 52 | url: `/orgs/${org}`, 53 | method: "DELETE" 54 | }, 55 | globalState 56 | ).then(() => { 57 | self.handleClose(); 58 | NotificationUtils.hideLoadingOverlay(globalState); 59 | if (history.length > 2) { 60 | history.goBack(); 61 | } else { 62 | history.push("/my-orgs"); 63 | } 64 | }).catch((err) => { 65 | let errorMessage; 66 | if (err instanceof HubApiError) { 67 | if (err.getMessage()) { 68 | errorMessage = err.getMessage(); 69 | } else { 70 | errorMessage = `Failed to delete organization - ${org}`; 71 | } 72 | } else { 73 | errorMessage = `Failed to delete organization - ${org}`; 74 | } 75 | NotificationUtils.hideLoadingOverlay(globalState); 76 | NotificationUtils.showNotification(errorMessage, NotificationUtils.Levels.ERROR, globalState); 77 | }); 78 | }; 79 | 80 | handleClose = () => { 81 | const {onClose} = this.props; 82 | onClose(); 83 | }; 84 | 85 | render() { 86 | const {classes, open, org} = this.props; 87 | 88 | return ( 89 |
90 | 91 | 92 | Do you really want to delete organization - {org}? 93 | 94 | 95 | 96 | If you delete this organization, all images in the organization will also be deleted. 97 | 98 | 99 | 100 | 101 | 104 | 105 | 106 |
107 | ); 108 | } 109 | 110 | } 111 | 112 | OrgDeleteDialog.propTypes = { 113 | classes: PropTypes.object.isRequired, 114 | globalState: PropTypes.instanceOf(StateHolder).isRequired, 115 | open: PropTypes.bool.isRequired, 116 | onClose: PropTypes.func.isRequired, 117 | org: PropTypes.string.isRequired, 118 | history: PropTypes.shape({ 119 | goBack: PropTypes.func.isRequired, 120 | length: PropTypes.number.isRequired, 121 | push: PropTypes.func.isRequired 122 | }) 123 | }; 124 | 125 | export default withStyles(styles)(withRouter(withGlobalState(OrgDeleteDialog))); 126 | -------------------------------------------------------------------------------- /components/portal/src/components/common/state/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | /* eslint react/prefer-stateless-function: ["off"] */ 20 | 21 | import CircularProgress from "@material-ui/core/CircularProgress/CircularProgress"; 22 | import Grid from "@material-ui/core/Grid/Grid"; 23 | import NotFound from "../error/NotFound"; 24 | import React from "react"; 25 | import StateHolder from "./stateHolder"; 26 | import {withRouter} from "react-router-dom"; 27 | import {withStyles} from "@material-ui/core"; 28 | import * as PropTypes from "prop-types"; 29 | 30 | // Creating a context that can be accessed 31 | const StateContext = React.createContext({}); 32 | 33 | const styles = () => ({ 34 | centerContainer: { 35 | position: "absolute", 36 | margin: "auto", 37 | top: 0, 38 | right: 0, 39 | bottom: 0, 40 | left: 0, 41 | width: "200px", 42 | height: "100px" 43 | } 44 | }); 45 | 46 | class UnStyledStateProvider extends React.Component { 47 | 48 | constructor(props) { 49 | super(props); 50 | 51 | this.state = { 52 | isLoading: true, 53 | isConfigAvailable: false 54 | }; 55 | 56 | this.mounted = false; 57 | this.stateHolder = new StateHolder(); 58 | } 59 | 60 | componentDidMount = () => { 61 | const self = this; 62 | self.mounted = true; 63 | self.stateHolder.loadConfig() 64 | .then(() => { 65 | if (self.mounted) { 66 | self.setState({ 67 | isLoading: false, 68 | isConfigAvailable: true 69 | }); 70 | } 71 | }) 72 | .catch(() => { 73 | if (self.mounted) { 74 | self.setState({ 75 | isLoading: false 76 | }); 77 | } 78 | }); 79 | }; 80 | 81 | componentWillUnmount = () => { 82 | this.mounted = false; 83 | }; 84 | 85 | render = () => { 86 | const {children, classes} = this.props; 87 | const {isLoading, isConfigAvailable} = this.state; 88 | 89 | const content = ( 90 | isConfigAvailable 91 | ? children 92 | : 93 | ); 94 | return ( 95 | 96 | { 97 | isLoading 98 | ? ( 99 | 101 | 102 |  Loading 103 | 104 | ) 105 | : content 106 | } 107 | 108 | ); 109 | }; 110 | 111 | } 112 | 113 | UnStyledStateProvider.propTypes = { 114 | children: PropTypes.any.isRequired, 115 | classes: PropTypes.object.isRequired, 116 | location: PropTypes.shape({ 117 | search: PropTypes.string.isRequired 118 | }).isRequired 119 | }; 120 | 121 | const StateProvider = withStyles(styles, {withTheme: true})(withRouter(UnStyledStateProvider)); 122 | 123 | /** 124 | * Higher Order Component for accessing the State Holder. 125 | * 126 | * @param {React.ComponentType} Component component which needs access to the state. 127 | * @returns {React.ComponentType} The new HOC with access to the state. 128 | */ 129 | const withGlobalState = (Component) => { 130 | class StateConsumer extends React.Component { 131 | 132 | render = () => { 133 | const {forwardedRef, ...otherProps} = this.props; 134 | 135 | return ( 136 | 137 | {(state) => } 138 | 139 | ); 140 | }; 141 | 142 | } 143 | 144 | StateConsumer.propTypes = { 145 | forwardedRef: PropTypes.any 146 | }; 147 | 148 | return React.forwardRef((props, ref) => ); 149 | }; 150 | 151 | export default withGlobalState; 152 | export {StateProvider, StateHolder}; 153 | -------------------------------------------------------------------------------- /components/portal/src/components/image/ImageDeleteDialog.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Button from "@material-ui/core/Button"; 20 | import Dialog from "@material-ui/core/Dialog"; 21 | import DialogActions from "@material-ui/core/DialogActions"; 22 | import DialogContent from "@material-ui/core/DialogContent"; 23 | import DialogContentText from "@material-ui/core/DialogContentText"; 24 | import DialogTitle from "@material-ui/core/DialogTitle"; 25 | import NotificationUtils from "../../utils/common/notificationUtils"; 26 | import React from "react"; 27 | import {withRouter} from "react-router-dom"; 28 | import {withStyles} from "@material-ui/core/styles/index"; 29 | import HttpUtils, {HubApiError} from "../../utils/api/httpUtils"; 30 | import withGlobalState, {StateHolder} from "../common/state"; 31 | import * as PropTypes from "prop-types"; 32 | 33 | const styles = (theme) => ({ 34 | dialogActions: { 35 | marginBottom: theme.spacing(2) 36 | }, 37 | deleteBtn: { 38 | color: "#e74c3c", 39 | borderColor: "#e74c3c", 40 | marginRight: theme.spacing(2) 41 | } 42 | }); 43 | 44 | class ImageDeleteDialog extends React.Component { 45 | 46 | handleDeleteImage = () => { 47 | const self = this; 48 | const {globalState, image, org, history} = self.props; 49 | NotificationUtils.showLoadingOverlay(`Deleting image ${org}/${image}`, globalState); 50 | HttpUtils.callHubAPI( 51 | { 52 | url: `/images/${org}/${image}`, 53 | method: "DELETE" 54 | }, 55 | globalState 56 | ).then(() => { 57 | self.handleClose(); 58 | NotificationUtils.hideLoadingOverlay(globalState); 59 | if (history.length > 2) { 60 | history.goBack(); 61 | } else { 62 | history.push("/my-images"); 63 | } 64 | }).catch((err) => { 65 | let errorMessage; 66 | if (err instanceof HubApiError) { 67 | if (err.getMessage()) { 68 | errorMessage = err.getMessage(); 69 | } else { 70 | errorMessage = `Failed to delete image - ${org}/${image}`; 71 | } 72 | } else { 73 | errorMessage = `Failed to delete image - ${org}/${image}`; 74 | } 75 | NotificationUtils.hideLoadingOverlay(globalState); 76 | NotificationUtils.showNotification(errorMessage, NotificationUtils.Levels.ERROR, globalState); 77 | }); 78 | }; 79 | 80 | handleClose = () => { 81 | const {onClose} = this.props; 82 | onClose(); 83 | }; 84 | 85 | render() { 86 | const {classes, open, image, org} = this.props; 87 | 88 | return ( 89 |
90 | 91 | 92 | Do you really want to delete image - {org}/{image}? 93 | 94 | 95 | 96 | If you delete this image, all image versions will also be deleted. 97 | 98 | 99 | 100 | 101 | 104 | 105 | 106 |
107 | ); 108 | } 109 | 110 | } 111 | 112 | ImageDeleteDialog.propTypes = { 113 | classes: PropTypes.object.isRequired, 114 | globalState: PropTypes.instanceOf(StateHolder).isRequired, 115 | open: PropTypes.bool.isRequired, 116 | onClose: PropTypes.func.isRequired, 117 | image: PropTypes.string.isRequired, 118 | org: PropTypes.string.isRequired, 119 | history: PropTypes.shape({ 120 | goBack: PropTypes.func.isRequired, 121 | length: PropTypes.number.isRequired, 122 | push: PropTypes.func.isRequired 123 | }) 124 | }; 125 | 126 | export default withStyles(styles)(withRouter(withGlobalState(ImageDeleteDialog))); 127 | -------------------------------------------------------------------------------- /components/portal/src/components/image/version/VersionDeleteDialog.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import Button from "@material-ui/core/Button"; 20 | import Dialog from "@material-ui/core/Dialog"; 21 | import DialogActions from "@material-ui/core/DialogActions"; 22 | import DialogContent from "@material-ui/core/DialogContent"; 23 | import DialogContentText from "@material-ui/core/DialogContentText"; 24 | import DialogTitle from "@material-ui/core/DialogTitle"; 25 | import NotificationUtils from "../../../utils/common/notificationUtils"; 26 | import React from "react"; 27 | import {withRouter} from "react-router-dom"; 28 | import {withStyles} from "@material-ui/core/styles/index"; 29 | import HttpUtils, {HubApiError} from "../../../utils/api/httpUtils"; 30 | import withGlobalState, {StateHolder} from "../../common/state/index"; 31 | import * as PropTypes from "prop-types"; 32 | 33 | const styles = (theme) => ({ 34 | dialogActions: { 35 | marginBottom: theme.spacing(2) 36 | }, 37 | deleteBtn: { 38 | color: "#e74c3c", 39 | borderColor: "#e74c3c", 40 | marginRight: theme.spacing(2) 41 | } 42 | }); 43 | 44 | class VersionDeleteDialog extends React.Component { 45 | 46 | handleDeleteVersion = () => { 47 | const self = this; 48 | const {globalState, org, image, version, history} = self.props; 49 | NotificationUtils.showLoadingOverlay(`Deleting image ${org}/${image}`, globalState); 50 | HttpUtils.callHubAPI( 51 | { 52 | url: `/artifacts/${org}/${image}/${version}`, 53 | method: "DELETE" 54 | }, 55 | globalState 56 | ).then(() => { 57 | self.handleClose(); 58 | NotificationUtils.hideLoadingOverlay(globalState); 59 | if (history.length > 2) { 60 | history.goBack(); 61 | } else { 62 | history.push(`/images/${org}/${image}`); 63 | } 64 | }).catch((err) => { 65 | let errorMessage; 66 | if (err instanceof HubApiError) { 67 | if (err.getMessage()) { 68 | errorMessage = err.getMessage(); 69 | } else { 70 | errorMessage = `Failed to delete image - ${org}/${image}`; 71 | } 72 | } else { 73 | errorMessage = `Failed to delete image - ${org}/${image}`; 74 | } 75 | NotificationUtils.hideLoadingOverlay(globalState); 76 | NotificationUtils.showNotification(errorMessage, NotificationUtils.Levels.ERROR, globalState); 77 | }); 78 | }; 79 | 80 | handleClose = () => { 81 | const {onClose} = this.props; 82 | onClose(); 83 | }; 84 | 85 | render() { 86 | const {classes, open, org, image, version} = this.props; 87 | 88 | return ( 89 |
90 | 91 | 92 | Do you really want to delete image version - {org}/{image}:{version}? 93 | 94 | 95 | 96 | If you delete this image version, it will no longer be accessible through Cellery Hub. 97 | 98 | 99 | 100 | 101 | 104 | 105 | 106 |
107 | ); 108 | } 109 | 110 | } 111 | 112 | VersionDeleteDialog.propTypes = { 113 | classes: PropTypes.object.isRequired, 114 | globalState: PropTypes.instanceOf(StateHolder).isRequired, 115 | open: PropTypes.bool.isRequired, 116 | onClose: PropTypes.func.isRequired, 117 | org: PropTypes.string.isRequired, 118 | image: PropTypes.string.isRequired, 119 | version: PropTypes.string.isRequired, 120 | history: PropTypes.shape({ 121 | goBack: PropTypes.func.isRequired, 122 | length: PropTypes.number.isRequired, 123 | push: PropTypes.func.isRequired 124 | }) 125 | }; 126 | 127 | export default withStyles(styles)(withRouter(withGlobalState(VersionDeleteDialog))); 128 | -------------------------------------------------------------------------------- /components/portal/src/components/org/MemberList.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. 3 | * 4 | * WSO2 Inc. licenses this file to you under the Apache License, 5 | * Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, 12 | * software distributed under the License is distributed on an 13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | * KIND, either express or implied. See the License for the 15 | * specific language governing permissions and limitations 16 | * under the License. 17 | */ 18 | 19 | import FormControl from "@material-ui/core/FormControl"; 20 | import Grid from "@material-ui/core/Grid"; 21 | import IconButton from "@material-ui/core/IconButton"; 22 | import Input from "@material-ui/core/Input"; 23 | import InputAdornment from "@material-ui/core/InputAdornment"; 24 | import MenuItem from "@material-ui/core/MenuItem"; 25 | import MuiDataTable from "mui-datatables"; 26 | import React from "react"; 27 | import SearchIcon from "@material-ui/icons/Search"; 28 | import Select from "@material-ui/core/Select"; 29 | import {withStyles} from "@material-ui/core/styles"; 30 | import * as PropTypes from "prop-types"; 31 | 32 | const styles = (theme) => ({ 33 | content: { 34 | paddingTop: theme.spacing(4) 35 | }, 36 | formControl: { 37 | minWidth: "100%" 38 | }, 39 | table: { 40 | marginTop: theme.spacing(2), 41 | boxShadow: "none" 42 | } 43 | }); 44 | 45 | const data = [ 46 | { 47 | name: "John", 48 | role: "admin" 49 | }, 50 | { 51 | name: "Mark", 52 | role: "member" 53 | } 54 | ]; 55 | 56 | class MemberList extends React.Component { 57 | 58 | constructor(props) { 59 | super(props); 60 | this.state = { 61 | role: "Member", 62 | isAdmin: false 63 | }; 64 | } 65 | 66 | handleRoleChange = (event) => { 67 | this.setState({ 68 | role: event.target.value 69 | }); 70 | }; 71 | 72 | render = () => { 73 | const {classes} = this.props; 74 | const {isAdmin} = this.state; 75 | const columns = [ 76 | { 77 | name: "name", 78 | label: "Name" 79 | }, 80 | { 81 | name: "role", 82 | label: "Role/State", 83 | options: { 84 | customBodyRender: (value) => { 85 | if (isAdmin) { 86 | return ; 93 | } 94 | return {value}; 95 | } 96 | } 97 | } 98 | ]; 99 | const tableOptions = { 100 | download: false, 101 | search: false, 102 | selectableRows: false, 103 | print: false, 104 | filter: false, 105 | responsive: "scroll", 106 | sort: true, 107 | rowHover: false, 108 | viewColumns: false 109 | }; 110 | 111 | return ( 112 |
113 |
114 | 115 | 116 | 117 | 120 | 121 | 122 | 123 | 124 | }/> 125 | 126 | 127 | 128 | 130 | 131 | 132 |
133 |
134 | ); 135 | } 136 | 137 | } 138 | 139 | MemberList.propTypes = { 140 | classes: PropTypes.object.isRequired, 141 | history: PropTypes.shape({ 142 | goBack: PropTypes.func.isRequired 143 | }), 144 | organization: PropTypes.string.isRequired 145 | }; 146 | 147 | export default withStyles(styles)(MemberList); 148 | -------------------------------------------------------------------------------- /components/docker-auth/test/init.sql: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # 3 | # Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License 16 | # 17 | # ------------------------------------------------------------------------ 18 | 19 | DROP DATABASE IF EXISTS CELLERY_HUB; 20 | CREATE DATABASE CELLERY_HUB; 21 | USE CELLERY_HUB; 22 | 23 | CREATE USER IF NOT EXISTS 'celleryhub'@'%' IDENTIFIED BY 'celleryhub'; 24 | GRANT ALL ON CELLERY_HUB.* TO 'celleryhub'@'%'; 25 | 26 | # This table is used for acquiring the MySQL write lock for a specific registry artifact 27 | CREATE TABLE IF NOT EXISTS REGISTRY_ARTIFACT_LOCK 28 | ( 29 | ARTIFACT_NAME VARCHAR(255) NOT NULL, 30 | LOCK_COUNT INT DEFAULT 0, 31 | PRIMARY KEY (ARTIFACT_NAME) 32 | ) 33 | ENGINE = InnoDB 34 | DEFAULT CHARSET = latin1; 35 | 36 | CREATE TABLE IF NOT EXISTS REGISTRY_ORGANIZATION 37 | ( 38 | ORG_NAME VARCHAR(255) NOT NULL, 39 | DESCRIPTION BLOB, 40 | SUMMARY VARCHAR(255) DEFAULT "", 41 | WEBSITE_URL VARCHAR(255) DEFAULT "", 42 | DEFAULT_IMAGE_VISIBILITY ENUM ("PUBLIC", "PRIVATE") NOT NULL DEFAULT "PUBLIC", 43 | FIRST_AUTHOR VARCHAR(255) NOT NULL, 44 | CREATED_DATE DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 45 | PRIMARY KEY (ORG_NAME) 46 | ) 47 | ENGINE = InnoDB 48 | DEFAULT CHARSET = latin1; 49 | 50 | CREATE TABLE IF NOT EXISTS REGISTRY_ORG_USER_MAPPING 51 | ( 52 | USER_UUID VARCHAR(36) NOT NULL, 53 | ORG_NAME VARCHAR(255) NOT NULL, 54 | USER_ROLE VARCHAR(255) NOT NULL, 55 | CREATED_DATE DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 56 | PRIMARY KEY (USER_UUID, ORG_NAME), 57 | FOREIGN KEY (ORG_NAME) REFERENCES REGISTRY_ORGANIZATION (ORG_NAME) 58 | ON DELETE CASCADE 59 | ) 60 | ENGINE = InnoDB 61 | DEFAULT CHARSET = latin1; 62 | 63 | CREATE TABLE IF NOT EXISTS REGISTRY_ARTIFACT_IMAGE 64 | ( 65 | ARTIFACT_IMAGE_ID VARCHAR(36) NOT NULL, 66 | ORG_NAME VARCHAR(255) NOT NULL, 67 | IMAGE_NAME VARCHAR(255) NOT NULL, 68 | SUMMARY VARCHAR(255) DEFAULT "", 69 | DESCRIPTION BLOB, 70 | FIRST_AUTHOR VARCHAR(255) NOT NULL, 71 | VISIBILITY ENUM ("PUBLIC", "PRIVATE") NOT NULL, 72 | PRIMARY KEY (ARTIFACT_IMAGE_ID), 73 | CONSTRAINT UC_ARTIFACT_IMG UNIQUE (ORG_NAME, IMAGE_NAME), 74 | FOREIGN KEY (ORG_NAME) REFERENCES REGISTRY_ORGANIZATION (ORG_NAME) 75 | ON DELETE CASCADE 76 | ) 77 | ENGINE = InnoDB 78 | DEFAULT CHARSET = latin1; 79 | 80 | CREATE TABLE IF NOT EXISTS IMAGE_KEYWORDS 81 | ( 82 | ARTIFACT_IMAGE_ID VARCHAR(36) NOT NULL, 83 | KEYWORD VARCHAR(36) NOT NULL, 84 | PRIMARY KEY (ARTIFACT_IMAGE_ID, KEYWORD), 85 | FOREIGN KEY (ARTIFACT_IMAGE_ID) REFERENCES REGISTRY_ARTIFACT_IMAGE (ARTIFACT_IMAGE_ID) 86 | ON DELETE CASCADE 87 | ) 88 | ENGINE = InnoDB 89 | DEFAULT CHARSET = latin1; 90 | 91 | CREATE TABLE IF NOT EXISTS REGISTRY_ARTIFACT 92 | ( 93 | ARTIFACT_ID VARCHAR(36) NOT NULL, 94 | ARTIFACT_IMAGE_ID VARCHAR(36) NOT NULL, 95 | VERSION VARCHAR(50) NOT NULL, 96 | DESCRIPTION BLOB, 97 | PULL_COUNT INT UNSIGNED DEFAULT 0, 98 | PUSH_COUNT INT UNSIGNED DEFAULT 0, 99 | LAST_AUTHOR VARCHAR(255) NOT NULL, 100 | FIRST_AUTHOR VARCHAR(255) NOT NULL, 101 | METADATA BLOB NOT NULL, 102 | VERIFIED BOOL DEFAULT FALSE, 103 | STATEFUL BOOL DEFAULT FALSE, 104 | CREATED_DATE DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 105 | UPDATED_DATE DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 106 | PRIMARY KEY (ARTIFACT_ID), 107 | CONSTRAINT UC_ARTIFACT UNIQUE (ARTIFACT_IMAGE_ID, VERSION), 108 | FOREIGN KEY (ARTIFACT_IMAGE_ID) REFERENCES REGISTRY_ARTIFACT_IMAGE (ARTIFACT_IMAGE_ID) 109 | ON DELETE CASCADE 110 | ) 111 | ENGINE = InnoDB 112 | DEFAULT CHARSET = latin1; 113 | 114 | CREATE TABLE IF NOT EXISTS REGISTRY_ARTIFACT_INGRESS 115 | ( 116 | ARTIFACT_ID VARCHAR(36) NOT NULL, 117 | INGRESS_TYPE VARCHAR(36) NOT NULL, 118 | PRIMARY KEY (ARTIFACT_ID, INGRESS_TYPE), 119 | FOREIGN KEY (ARTIFACT_ID) REFERENCES REGISTRY_ARTIFACT (ARTIFACT_ID) 120 | ON DELETE CASCADE 121 | ) 122 | ENGINE = InnoDB 123 | DEFAULT CHARSET = latin1; 124 | 125 | CREATE TABLE IF NOT EXISTS REGISTRY_ARTIFACT_LABEL 126 | ( 127 | ARTIFACT_ID VARCHAR(36) NOT NULL, 128 | LABEL_KEY VARCHAR(36) NOT NULL, 129 | LABEL_VALUE VARCHAR(36) NOT NULL, 130 | PRIMARY KEY (ARTIFACT_ID, LABEL_KEY), 131 | FOREIGN KEY (ARTIFACT_ID) REFERENCES REGISTRY_ARTIFACT (ARTIFACT_ID) 132 | ON DELETE CASCADE 133 | ) 134 | ENGINE = InnoDB 135 | DEFAULT CHARSET = latin1; 136 | 137 | -- CELLERY HUB ENDS -- -------------------------------------------------------------------------------- /components/api/gen/schema.bal: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------ 2 | // 3 | // Copyright 2019 WSO2, Inc. (http://wso2.com) 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License 16 | // 17 | // ------------------------------------------------------------------------ 18 | 19 | public type TokensResponse record { 20 | string accessToken; 21 | string idToken; 22 | }; 23 | 24 | public type OrgCreateRequest record { 25 | string orgName; 26 | string description; 27 | string websiteUrl; 28 | string defaultVisibility; 29 | }; 30 | 31 | public type OrgResponse record { 32 | byte[]? description; 33 | string summary; 34 | string websiteUrl; 35 | string firstAuthor; 36 | string createdTimestamp; 37 | string userRole; 38 | }; 39 | 40 | // Uses for get a specific artifact 41 | public type Artifact record { 42 | byte[]? description; 43 | int? pullCount; 44 | string lastAuthor; 45 | string? updatedTimestamp; 46 | byte[] metadata; 47 | string userRole; 48 | }; 49 | 50 | 51 | public type Count record { 52 | int count; 53 | }; 54 | 55 | // Uses for list down artifacts 56 | public type ArtifactDatum record { 57 | string artifactImageId; 58 | string artifactId; 59 | byte[]? description; 60 | int? pullCount; 61 | string lastAuthor; 62 | string? updatedTimestamp; 63 | string artifactVersion; 64 | }; 65 | 66 | public type ArtifactDatumResponse record { 67 | string artifactImageId; 68 | string artifactId; 69 | string description; 70 | int? pullCount; 71 | string lastAuthor; 72 | string? updatedTimestamp; 73 | string artifactVersion; 74 | }; 75 | 76 | public type ArtifactListArrayResponse record { 77 | int count; 78 | ArtifactDatumResponse[] data; 79 | }; 80 | 81 | public type Image record { 82 | string imageId; 83 | string orgName; 84 | string imageName; 85 | string summary; 86 | byte[]? description; 87 | string firstAuthor; 88 | string visibility; 89 | decimal? pushCount; 90 | decimal? pullCount; 91 | string userRole; 92 | }; 93 | 94 | public type ImageResponse record { 95 | string imageId; 96 | string orgName; 97 | string imageName; 98 | string summary; 99 | string description; 100 | string firstAuthor; 101 | string visibility; 102 | decimal? pushCount; 103 | decimal? pullCount; 104 | string[] keywords; 105 | }; 106 | 107 | public type StringRecord record { 108 | string value; 109 | }; 110 | 111 | public type OrgListResponse record { 112 | int count; 113 | OrgListResponseAtom[] data; 114 | }; 115 | 116 | public type OrgListAtom record { 117 | string orgName; 118 | string summary; 119 | byte[]? description; 120 | int membersCount; 121 | }; 122 | 123 | public type OrgListResponseAtom record { 124 | string orgName; 125 | string summary; 126 | string description; 127 | int membersCount; 128 | int imageCount; 129 | }; 130 | 131 | public type OrgListResponseImageCount record { 132 | string orgName; 133 | int imageCount; 134 | }; 135 | 136 | public type ErrorResponse record { 137 | int code; 138 | string message; 139 | string description; 140 | }; 141 | 142 | public type User record { 143 | string userId; 144 | string roles; 145 | }; 146 | 147 | public type UserResponse record { 148 | string userId; 149 | string displayName; 150 | string firstName; 151 | string lastName; 152 | string email; 153 | string roles; 154 | }; 155 | 156 | public type UserListResponse record { 157 | int count; 158 | UserResponse[] data; 159 | }; 160 | 161 | public type ImagesListResponse record { 162 | int count; 163 | ImagesListResponseAtom[] data; 164 | }; 165 | 166 | public type OrgImagesListResponse record { 167 | int count; 168 | OrgImagesListResponseAtom[] data; 169 | }; 170 | 171 | public type ImagesListAtom record { 172 | string orgName; 173 | string imageName; 174 | string summary; 175 | byte[]? description; 176 | decimal? pullCount; 177 | string? updatedTimestamp; 178 | string visibility; 179 | }; 180 | 181 | public type ImagesListResponseAtom record { 182 | string orgName; 183 | string imageName; 184 | string summary; 185 | string description; 186 | decimal? pullCount; 187 | string? updatedTimestamp; 188 | string visibility; 189 | }; 190 | 191 | public type OrgImagesListAtom record { 192 | string imageName; 193 | string summary; 194 | byte[]? description; 195 | decimal? pullCount; 196 | string? updatedTimestamp; 197 | string visibility; 198 | }; 199 | 200 | public type OrgImagesListResponseAtom record { 201 | string imageName; 202 | string summary; 203 | string description; 204 | decimal? pullCount; 205 | string? updatedTimestamp; 206 | string visibility; 207 | }; 208 | 209 | public type ImageUpdateRequest record { 210 | string description; 211 | string summary; 212 | string[] keywords; 213 | }; 214 | 215 | public type OrgUpdateRequest record { 216 | string description; 217 | string summary; 218 | string websiteUrl; 219 | }; 220 | 221 | public type ArtifactUpdateRequest record { 222 | string description; 223 | }; 224 | --------------------------------------------------------------------------------