Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ui-client/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/*
.env
.env.local
.DS_Store
package-lock.json
3 changes: 3 additions & 0 deletions ui-client/backend/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}
12 changes: 12 additions & 0 deletions ui-client/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Backend API for MFT User Interface

**Frontend Code:** https://github.com/ganning127/mft-ui-nextjs

**Backend Code:** This repository

---

### Running this code
1. Clone the repository
2. Run `npm i`
3. Run `npx tsx main.ts` to run `main.ts`
123 changes: 123 additions & 0 deletions ui-client/backend/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// To run this file, do: `npx tsx main.ts`
// You need: `npm i -D tsx`

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const express = require('express');
import {loadSync} from "@grpc/proto-loader";
import {loadPackageDefinition, ChannelCredentials, GrpcObject} from "@grpc/grpc-js";
import lodash from 'lodash';
const {get} = lodash;
var cors = require('cors');

const app = express();
const port = 5500;
const allowedOrigins = ["http://localhost:3000"];

var PROTO_PATH = 'proto/StorageCommon.proto';
var TRANSFER_API_PROTO_PATH = 'proto/api/stub/src/main/proto/MFTTransferApi.proto';

const packageDefinition = loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
arrays: true,
defaults: true,
oneofs: true,
});

var proto = loadPackageDefinition(packageDefinition)
const Service = get(proto, "org.apache.airavata.mft.resource.stubs.storage.common.StorageCommonService");
const serviceClient = new Service("localhost:7003", ChannelCredentials.createInsecure());

const transferApiPackageDefinition = loadSync(TRANSFER_API_PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
arrays: true,
defaults: true,
oneofs: true,
});

var transferApiProto = loadPackageDefinition(transferApiPackageDefinition)
const TransferService = get(transferApiProto, "org.apache.airavata.mft.api.service.MFTTransferService");
const TransferServiceClient = new TransferService("localhost:7003", ChannelCredentials.createInsecure());


app.use(cors());

app.use(cors({
origin: function (origin, callback) {
// allow requests with no origin
// (like mobile apps or curl requests)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
var msg = 'The CORS policy for this site does not allow access from the specified Origin.';
return callback(new Error(msg), false);
}
return callback(null, true);
}
}));

app.get('/', (req, res) => {
res.json({
message: "You've reached te MFT API!"
});
});

app.get('/list-storages', (req, res) => {
serviceClient.listStorages({}, (err, resp) => {
if (err) {
res.json(err);
} else {
res.json(resp);
}
});
});

app.get('/list-storages/:storageId', (req, res) => {

const storageId = req.params.storageId;
const storageType = req.headers.storagetype;
const path = req.headers.path;

if (storageType === "LOCAL") {
// the secretID is just a blank string for local storage
TransferServiceClient.resourceMetadata({"idRequest" :{
"resourcePath": path,
"storageId": storageId,
"secretId": "",
"recursiveSearch": true,
}}, (err, resp) => {
if (err) {
res.json(err);
} else {
res.json(resp);
}
});
} else {
serviceClient.getSecretForStorage({"storageId": storageId}, (err, resp) => {
if (err) {
res.json(err);
} else {
const secretId = resp.secretId;
TransferServiceClient.resourceMetadata({"idRequest" :{
"resourcePath": path,
"storageId": storageId,
"secretId": secretId,
"recursiveSearch": true,
}}, (err, resp) => {
if (err) {
res.json(err);
} else {
res.json(resp);
}
});
}});
}
});


app.listen(port, () => {
console.log(`MFT backend listening on port ${port}`);
});
25 changes: 25 additions & 0 deletions ui-client/backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "mft-ui-backend",
"version": "1.0.0",
"description": "",
"main": "main.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.10.6",
"@grpc/proto-loader": "^0.7.12",
"cors": "^2.8.5",
"express": "^4.19.2",
"grpc_tools_node_protoc_ts": "^5.3.3",
"grpc-tools": "^1.12.4",
"lodash": "^4.17.21"
},
"type": "module",
"devDependencies": {
"tsx": "^4.7.2"
}
}
103 changes: 103 additions & 0 deletions ui-client/backend/proto/StorageCommon.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

syntax = "proto3";

option java_multiple_files = true;
package org.apache.airavata.mft.resource.stubs.storage.common;

enum StorageType {
S3 = 0;
SCP = 1;
FTP = 2;
LOCAL = 3;
BOX = 4;
DROPBOX = 5;
GCS = 6;
AZURE = 7;
SWIFT = 8;
ODATA = 9;
HTTP = 10;
}

enum Error {
NOT_FOUND = 0;
NO_PERMISSION = 1;
LIMIT_OVERFLOWED = 2;
}

message StorageTypeResolveRequest {
string storageId = 1;
}

message StorageTypeResolveResponse {
string storageId = 1;
string storageName = 2;
StorageType storageType = 3;
Error error = 4;
}

message SecretForStorage {
string storageId = 1;
string secretId = 2;
StorageType storageType = 3;
Error error = 4;
}

message SecretForStorageGetRequest {
string storageId = 1;
}

message SecretForStorageDeleteRequest {
string storageId = 1;
}

message SecretForStorageDeleteResponse {
bool status = 1;
}

message StorageListEntry {
string storageId = 1;
string storageName = 2;
StorageType storageType = 3;
}

message StorageListResponse {
repeated StorageListEntry storageList = 1;
}

message StorageListRequest {
int32 pageNumber = 1;
int32 pageSize = 2;
}

message StorageSearchRequest {
oneof searchQuery {
string storageId = 1;
string storageName = 2;
StorageType storageType = 3;
}
}

service StorageCommonService {
rpc resolveStorageType (StorageTypeResolveRequest) returns (StorageTypeResolveResponse);
rpc registerSecretForStorage(SecretForStorage) returns (SecretForStorage);
rpc getSecretForStorage(SecretForStorageGetRequest) returns (SecretForStorage);
rpc deleteSecretsForStorage(SecretForStorageDeleteRequest) returns (SecretForStorageDeleteResponse);
rpc searchStorages(StorageSearchRequest) returns (StorageListResponse);
rpc listStorages(StorageListRequest) returns (StorageListResponse);
}
53 changes: 53 additions & 0 deletions ui-client/backend/proto/api/client/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--


Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mft-api</artifactId>
<groupId>org.apache.airavata</groupId>
<version>0.01-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>mft-api-client</artifactId>

<dependencies>
<dependency>
<groupId>org.apache.airavata</groupId>
<artifactId>mft-api-stub</artifactId>
<version>0.01-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.airavata</groupId>
<artifactId>mft-resource-service-client</artifactId>
<version>0.01-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.airavata</groupId>
<artifactId>mft-secret-service-client</artifactId>
<version>0.01-SNAPSHOT</version>
</dependency>
</dependencies>

</project>
Loading