From 4bdda4f1c4a5e4df7b533aa0cf15254344ef0711 Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Fri, 7 Jul 2023 13:40:18 -0400 Subject: [PATCH 01/11] first folder --- java/wipe_appwrite_collection/Index.java | 283 ++++++++++++++++++++++ java/wipe_appwrite_collection/README.md | 91 +++++++ java/wipe_appwrite_collection/deps.gradle | 4 + 3 files changed, 378 insertions(+) create mode 100644 java/wipe_appwrite_collection/Index.java create mode 100644 java/wipe_appwrite_collection/README.md create mode 100644 java/wipe_appwrite_collection/deps.gradle diff --git a/java/wipe_appwrite_collection/Index.java b/java/wipe_appwrite_collection/Index.java new file mode 100644 index 00000000..ace28ef1 --- /dev/null +++ b/java/wipe_appwrite_collection/Index.java @@ -0,0 +1,283 @@ +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import com.google.gson.Gson; +import org.apache.commons.validator.routines.UrlValidator; + +// List of supported providers +private enum Provider { + + BITLY("bitly"), + TINY_URL("tinyurl"); + + private final String name; + + Provider(String name) { + this.name = name; + } + + static boolean validateProvider(String name) { + for(Provider providerName: Provider.values()) { + if(providerName.name.equals(name)) { + return true; + } + } + + return false; + } + + String getName() { + return name; + } +} + +final Gson gson = new Gson(); + +final Map endpointsMap = Map.of( + "bitly", "https://api-ssl.bitly.com/v4/shorten", + "tinyurl", "https://api.tinyurl.com/create" +); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + + // Validate that values present in the request are not empty (payload, variables) + RuntimeResponse errorResponse = checkEmptyPayloadAndVariables(req, res); + if(errorResponse != null) { + return errorResponse; + } + + // Validate the requested payload (provider and URL) + String payloadString = req.getPayload(); + Map payload = gson.fromJson(payloadString, Map.class); + + errorResponse = validatePayload(payload, res); + if(errorResponse != null) { + return errorResponse; + } + + // Generate short url + String provider = payload.get("provider").toString(); + String url = payload.get("url").toString(); + + // Validate that the API key is not empty + String apiKeyVariable = Provider.BITLY.getName().equals(provider) ? "BITLY_API_KEY" : "TINYURL_API_KEY"; + + errorResponse = checkEmptyAPIKey(req, res, apiKeyVariable); + if(errorResponse != null) { + return errorResponse; + } + + String apiKey = req.getVariables().get(apiKeyVariable); + + String shortUrl = ""; + + Map responseData = new HashMap<>(); + + try { + shortUrl = generateShortUrl(apiKey, provider, url); + } catch(Exception e) { + responseData.put("success", false); + responseData.put("message", "Something went wrong while generating the shortUrl, please check with the developers. Error: " + e.getMessage()); + return res.json(responseData); + } + + // Validate that the generated short URL is not empty + errorResponse = checkEmptyShortUrl(shortUrl, res); + if(errorResponse != null) { + return errorResponse; + } + + // Send response + responseData.put("success", true); + responseData.put("url", shortUrl); + + return res.json(responseData); +} + +/** + * This method validates that the generated short URL is not empty + * + * @param shortUrl is the URL to be validated + * @return null if shortURL is non-empty, otherwise an error response + */ +private RuntimeResponse checkEmptyShortUrl(String shortUrl, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + if(shortUrl == null || shortUrl.trim().isEmpty()) { + responseData.put("success", false); + responseData.put("message", "Blank or null shortUrl value is returned, please try again or check with the developers"); + return res.json(responseData); + } + + return null; +} + +/** + * This method validates that non-empty provider and URL are present in the payload + * It also validates that the requested provider is one of the supported providers + * + * @param payload is the object that contains the provider and the URL + * @return null if payload is valid, otherwise an error response + */ +private RuntimeResponse validatePayload(Map payload, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + // Validate that payload has both provider and url + if(!payload.containsKey("provider") || !payload.containsKey("url")) { + responseData.put("success", false); + responseData.put("message", "Payload must contain both provider and url data"); + return res.json(responseData); + } + + String provider = payload.get("provider").toString(); + String url = payload.get("url").toString(); + + // Validate the provider + if(!Provider.validateProvider(provider)) { + responseData.put("success", false); + String providerNames = Stream.of(Provider.values()) + .map(Provider::getName) + .collect(Collectors.joining(", ")); + responseData.put("message", "Provider " + provider + " is not supported currently. " + + "Only " + providerNames + " are supported"); + return res.json(responseData); + } + + // Validate the URL + UrlValidator urlValidator = new UrlValidator(); + if (!urlValidator.isValid(url)) { + responseData.put("success", false); + responseData.put("message", "Provided URL: " + url + " is not valid, please provide a valid, correctly formed URL"); + return res.json(responseData); + } + + return null; +} + +/** + * This function will validate that the payload and variables are non-empty in the request + * + * @param req is the received POST request + * @return null is nothing is empty, otherwise an error response + */ +private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + if(req.getPayload() == null || req.getPayload().trim().isEmpty() || req.getPayload().trim().equals("{}")) { + responseData.put("success", false); + responseData.put("message", "Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + } + + if(req.getVariables() == null) { + responseData.put("success", false); + responseData.put("message", "Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + return null; +} + +/** + * This method validates that a non-empty API key is present in variables + * + * @param req is the received POST request + * @return null if non-empty API key is present, otherwise an error response + */ +private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req, RuntimeResponse res, String apiKeyVariable) { + Map variables = req.getVariables(); + + if(!variables.containsKey(apiKeyVariable) + || variables.get(apiKeyVariable) == null + || variables.get(apiKeyVariable).trim().isEmpty()) { + Map responseData = new HashMap<>(); + responseData.put("success", false); + responseData.put("message", "Please pass a non-empty API Key " + apiKeyVariable + " for the provider"); + return res.json(responseData); + } + + return null; +} + +/** + * This method will generate a short URL for the given long URL and provider using the provider's API key + * It will generate the request body and parse the response according to the provider + * + * @param apiKey is the access token used by the provider to generate a short URL + * @param provider is the service that will generate the short URL. E.g. tinyurl, bitly + * @param url is the URL to be shortened + * @return the shortened URL + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String generateShortUrl(String apiKey, String provider, String url) throws Exception { + if(apiKey == null || apiKey.trim().isEmpty()) { + return null; + } + + String requestBody = ""; + + if(Provider.BITLY.getName().equals(provider)) { + requestBody = "{\"long_url\": \"" + url + "\"}"; + } else if(Provider.TINY_URL.getName().equals(provider)) { + requestBody = "{\"url\": \"" + url + "\"}"; + } + + if(requestBody.isEmpty()) { + return null; + } + + String response = getShortUrlFromProvider(endpointsMap.get(provider), requestBody, apiKey); + Map parsedResponse = gson.fromJson(response, Map.class); + + if(Provider.BITLY.getName().equals(provider)) { + return parsedResponse.get("link").toString(); + } else if(Provider.TINY_URL.getName().equals(provider)) { + Map responseData = (Map) parsedResponse.get("data"); + return responseData.get("tiny_url").toString(); + } + + return null; +} + +/** + * This method will send a POST request to the specified endpoint and return the provider's response + * + * @param endpointUrl is the provider's POST endpoint to which the URL generation request is to be sent + * @param requestBody is the Request Body for the POST request containing the URL to be shortened + * @param apiKey is the access token used by the provider to generate a short URL + * @return the provider's response to the POST request + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String getShortUrlFromProvider(String endpointUrl, String requestBody, String apiKey) throws Exception { + URL url = new URL(endpointUrl); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Authorization", "Bearer " + apiKey); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + + OutputStream os = con.getOutputStream(); + byte[] input = requestBody.getBytes("utf-8"); + os.write(input, 0, input.length); + + StringBuilder response = new StringBuilder(); + + BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); + String responseLine = null; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + + br.close(); + con.disconnect(); + + return response.toString(); +} \ No newline at end of file diff --git a/java/wipe_appwrite_collection/README.md b/java/wipe_appwrite_collection/README.md new file mode 100644 index 00000000..ef6ec7cf --- /dev/null +++ b/java/wipe_appwrite_collection/README.md @@ -0,0 +1,91 @@ +# 💻 Get Short URL + +A Java Cloud Function for generating a Short URL using [tinyurl](https://tinyurl.com/app) and [bitly](https://bitly.com/) + +Supported providers: tinyurl, bitly + +_Bitly Example input:_ + + + +```json +{ + "provider": "bitly", + "url": "https://google.com" +} +``` + +_Bitly Example output:_ + + +```json +{ + "success": true, + "url": "https://bit.ly/3CywbjA" +} +``` + +_Tinyurl Example input:_ + + + +```json +{ + "provider": "tinyurl", + "url": "https://google.com" +} +``` + +_Tinyurl Example output:_ + + +```json +{ + "success": true, + "url": "https://tinyurl.com/dck67zxk" +} +``` + +_Error Example output:_ + +```json +{ + "success": false, + "message":"Provided URL: https://xyz is not valid, please provide a valid, correctly formed URL" +} +``` + + +## 📝 Environment Variables + +List of environment variables used by this cloud function. These must be passed within 'variables' section of the request: + +**BITLY_API_KEY** - Pass this API key if the requested provider is bitly. This API key would be the access token used by bitly for generating a short URL. + +**TINYURL_API_KEY** - Pass this API key if the requested provider is tinyurl. This API key would be the access token used by tinyurl for generating a short URL. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd java/short_url_generator +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-11.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-11.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Java 11.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/java/wipe_appwrite_collection/deps.gradle b/java/wipe_appwrite_collection/deps.gradle new file mode 100644 index 00000000..16206c71 --- /dev/null +++ b/java/wipe_appwrite_collection/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'commons-validator:commons-validator:1.7' +} \ No newline at end of file From 4f9080b59d627ebd0ce4cff9f8b5961cc5678322 Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Fri, 7 Jul 2023 13:59:49 -0400 Subject: [PATCH 02/11] test1 --- java/wipe_appwrite_collection/Index.java | 283 ----------------------- java/wipe_appwrite_collection/README.md | 2 +- 2 files changed, 1 insertion(+), 284 deletions(-) diff --git a/java/wipe_appwrite_collection/Index.java b/java/wipe_appwrite_collection/Index.java index ace28ef1..e69de29b 100644 --- a/java/wipe_appwrite_collection/Index.java +++ b/java/wipe_appwrite_collection/Index.java @@ -1,283 +0,0 @@ -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.*; -import java.util.stream.*; -import java.net.HttpURLConnection; -import java.net.ProtocolException; -import java.net.URL; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStream; -import com.google.gson.Gson; -import org.apache.commons.validator.routines.UrlValidator; - -// List of supported providers -private enum Provider { - - BITLY("bitly"), - TINY_URL("tinyurl"); - - private final String name; - - Provider(String name) { - this.name = name; - } - - static boolean validateProvider(String name) { - for(Provider providerName: Provider.values()) { - if(providerName.name.equals(name)) { - return true; - } - } - - return false; - } - - String getName() { - return name; - } -} - -final Gson gson = new Gson(); - -final Map endpointsMap = Map.of( - "bitly", "https://api-ssl.bitly.com/v4/shorten", - "tinyurl", "https://api.tinyurl.com/create" -); - -public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { - - // Validate that values present in the request are not empty (payload, variables) - RuntimeResponse errorResponse = checkEmptyPayloadAndVariables(req, res); - if(errorResponse != null) { - return errorResponse; - } - - // Validate the requested payload (provider and URL) - String payloadString = req.getPayload(); - Map payload = gson.fromJson(payloadString, Map.class); - - errorResponse = validatePayload(payload, res); - if(errorResponse != null) { - return errorResponse; - } - - // Generate short url - String provider = payload.get("provider").toString(); - String url = payload.get("url").toString(); - - // Validate that the API key is not empty - String apiKeyVariable = Provider.BITLY.getName().equals(provider) ? "BITLY_API_KEY" : "TINYURL_API_KEY"; - - errorResponse = checkEmptyAPIKey(req, res, apiKeyVariable); - if(errorResponse != null) { - return errorResponse; - } - - String apiKey = req.getVariables().get(apiKeyVariable); - - String shortUrl = ""; - - Map responseData = new HashMap<>(); - - try { - shortUrl = generateShortUrl(apiKey, provider, url); - } catch(Exception e) { - responseData.put("success", false); - responseData.put("message", "Something went wrong while generating the shortUrl, please check with the developers. Error: " + e.getMessage()); - return res.json(responseData); - } - - // Validate that the generated short URL is not empty - errorResponse = checkEmptyShortUrl(shortUrl, res); - if(errorResponse != null) { - return errorResponse; - } - - // Send response - responseData.put("success", true); - responseData.put("url", shortUrl); - - return res.json(responseData); -} - -/** - * This method validates that the generated short URL is not empty - * - * @param shortUrl is the URL to be validated - * @return null if shortURL is non-empty, otherwise an error response - */ -private RuntimeResponse checkEmptyShortUrl(String shortUrl, RuntimeResponse res) { - Map responseData = new HashMap<>(); - - if(shortUrl == null || shortUrl.trim().isEmpty()) { - responseData.put("success", false); - responseData.put("message", "Blank or null shortUrl value is returned, please try again or check with the developers"); - return res.json(responseData); - } - - return null; -} - -/** - * This method validates that non-empty provider and URL are present in the payload - * It also validates that the requested provider is one of the supported providers - * - * @param payload is the object that contains the provider and the URL - * @return null if payload is valid, otherwise an error response - */ -private RuntimeResponse validatePayload(Map payload, RuntimeResponse res) { - Map responseData = new HashMap<>(); - - // Validate that payload has both provider and url - if(!payload.containsKey("provider") || !payload.containsKey("url")) { - responseData.put("success", false); - responseData.put("message", "Payload must contain both provider and url data"); - return res.json(responseData); - } - - String provider = payload.get("provider").toString(); - String url = payload.get("url").toString(); - - // Validate the provider - if(!Provider.validateProvider(provider)) { - responseData.put("success", false); - String providerNames = Stream.of(Provider.values()) - .map(Provider::getName) - .collect(Collectors.joining(", ")); - responseData.put("message", "Provider " + provider + " is not supported currently. " + - "Only " + providerNames + " are supported"); - return res.json(responseData); - } - - // Validate the URL - UrlValidator urlValidator = new UrlValidator(); - if (!urlValidator.isValid(url)) { - responseData.put("success", false); - responseData.put("message", "Provided URL: " + url + " is not valid, please provide a valid, correctly formed URL"); - return res.json(responseData); - } - - return null; -} - -/** - * This function will validate that the payload and variables are non-empty in the request - * - * @param req is the received POST request - * @return null is nothing is empty, otherwise an error response - */ -private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req, RuntimeResponse res) { - Map responseData = new HashMap<>(); - - if(req.getPayload() == null || req.getPayload().trim().isEmpty() || req.getPayload().trim().equals("{}")) { - responseData.put("success", false); - responseData.put("message", "Payload is empty, expected a payload with provider and URL"); - return res.json(responseData); - } - - if(req.getVariables() == null) { - responseData.put("success", false); - responseData.put("message", "Empty function variables found. You need to pass an API key for the provider"); - return res.json(responseData); - } - return null; -} - -/** - * This method validates that a non-empty API key is present in variables - * - * @param req is the received POST request - * @return null if non-empty API key is present, otherwise an error response - */ -private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req, RuntimeResponse res, String apiKeyVariable) { - Map variables = req.getVariables(); - - if(!variables.containsKey(apiKeyVariable) - || variables.get(apiKeyVariable) == null - || variables.get(apiKeyVariable).trim().isEmpty()) { - Map responseData = new HashMap<>(); - responseData.put("success", false); - responseData.put("message", "Please pass a non-empty API Key " + apiKeyVariable + " for the provider"); - return res.json(responseData); - } - - return null; -} - -/** - * This method will generate a short URL for the given long URL and provider using the provider's API key - * It will generate the request body and parse the response according to the provider - * - * @param apiKey is the access token used by the provider to generate a short URL - * @param provider is the service that will generate the short URL. E.g. tinyurl, bitly - * @param url is the URL to be shortened - * @return the shortened URL - * @throws Exception in case of malformed URL, I/O exception, etc. - */ -private String generateShortUrl(String apiKey, String provider, String url) throws Exception { - if(apiKey == null || apiKey.trim().isEmpty()) { - return null; - } - - String requestBody = ""; - - if(Provider.BITLY.getName().equals(provider)) { - requestBody = "{\"long_url\": \"" + url + "\"}"; - } else if(Provider.TINY_URL.getName().equals(provider)) { - requestBody = "{\"url\": \"" + url + "\"}"; - } - - if(requestBody.isEmpty()) { - return null; - } - - String response = getShortUrlFromProvider(endpointsMap.get(provider), requestBody, apiKey); - Map parsedResponse = gson.fromJson(response, Map.class); - - if(Provider.BITLY.getName().equals(provider)) { - return parsedResponse.get("link").toString(); - } else if(Provider.TINY_URL.getName().equals(provider)) { - Map responseData = (Map) parsedResponse.get("data"); - return responseData.get("tiny_url").toString(); - } - - return null; -} - -/** - * This method will send a POST request to the specified endpoint and return the provider's response - * - * @param endpointUrl is the provider's POST endpoint to which the URL generation request is to be sent - * @param requestBody is the Request Body for the POST request containing the URL to be shortened - * @param apiKey is the access token used by the provider to generate a short URL - * @return the provider's response to the POST request - * @throws Exception in case of malformed URL, I/O exception, etc. - */ -private String getShortUrlFromProvider(String endpointUrl, String requestBody, String apiKey) throws Exception { - URL url = new URL(endpointUrl); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - - con.setRequestMethod("POST"); - con.setRequestProperty("Content-Type", "application/json"); - con.setRequestProperty("Authorization", "Bearer " + apiKey); - con.setRequestProperty("Accept", "application/json"); - con.setDoOutput(true); - - OutputStream os = con.getOutputStream(); - byte[] input = requestBody.getBytes("utf-8"); - os.write(input, 0, input.length); - - StringBuilder response = new StringBuilder(); - - BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); - String responseLine = null; - while ((responseLine = br.readLine()) != null) { - response.append(responseLine.trim()); - } - - br.close(); - con.disconnect(); - - return response.toString(); -} \ No newline at end of file diff --git a/java/wipe_appwrite_collection/README.md b/java/wipe_appwrite_collection/README.md index ef6ec7cf..31762c3a 100644 --- a/java/wipe_appwrite_collection/README.md +++ b/java/wipe_appwrite_collection/README.md @@ -1,4 +1,4 @@ -# 💻 Get Short URL +# 💻 Wipe Appwrite Collection A Java Cloud Function for generating a Short URL using [tinyurl](https://tinyurl.com/app) and [bitly](https://bitly.com/) From aff7bdf0e86f6c591e8c29301d516eec63b93644 Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Fri, 7 Jul 2023 15:38:00 -0400 Subject: [PATCH 03/11] First coding --- java/collection_wiper/Index.java | 36 +++++++++++++++++++ .../README.md | 2 +- .../deps.gradle | 2 +- java/wipe_appwrite_collection/Index.java | 0 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 java/collection_wiper/Index.java rename java/{wipe_appwrite_collection => collection_wiper}/README.md (98%) rename java/{wipe_appwrite_collection => collection_wiper}/deps.gradle (53%) delete mode 100644 java/wipe_appwrite_collection/Index.java diff --git a/java/collection_wiper/Index.java b/java/collection_wiper/Index.java new file mode 100644 index 00000000..7c85d445 --- /dev/null +++ b/java/collection_wiper/Index.java @@ -0,0 +1,36 @@ +package java.collection_wiper; +import okhttp3.*; +import java.io.IOException; + +public AppwriteCollectionWiper { + private static final String API_ENDPOINT = "http://localhost/v1"; + private static final String PROJECT_ID = "649f0fde61b9f6d9d83c"; + private static final String COLLECTION_ID = ""; + private static final String API_KEY = "9761bd7ab2d242e1e1343cf2757e51a2f28befda464a168947f308fca1cf4d98f4d749b90291ff3d35155025018c856aeaf3d597cb1ec6ad7ce067b0d10e87eb586b2f9ca3e0da9c81a8509acdefae6c2632f95ea4f6986bdaffe8a8dc15eaa40332ff7fd059b00f6aad1ef92618a903aa7b6b273903e3c750296b75d227b182"; + + public static void main(String[] args) { + wipeAppwriteCollection(); + } + + public static void wipeAppwriteCollection() { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url(API_ENDPOINT + "/database/collections/" + COLLECTION_ID + "/documents") + .addHeader("X-Appwrite-Project", PROJECT_ID) + .addHeader("X-Appwrite-Key", API_KEY) + .delete() + .build(); + + Call call = client.newCall(request); + try { + Response response = call.execute(); + if (response.isSuccessful()) { + System.out.println("Collection wiped successfully."); + } else { + System.out.println("Failed to wipe collection. Error: " + response.body().string()); + } + } catch (IOException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } +} diff --git a/java/wipe_appwrite_collection/README.md b/java/collection_wiper/README.md similarity index 98% rename from java/wipe_appwrite_collection/README.md rename to java/collection_wiper/README.md index 31762c3a..aaa422c1 100644 --- a/java/wipe_appwrite_collection/README.md +++ b/java/collection_wiper/README.md @@ -1,4 +1,4 @@ -# 💻 Wipe Appwrite Collection +# 💻 Collection Wiper A Java Cloud Function for generating a Short URL using [tinyurl](https://tinyurl.com/app) and [bitly](https://bitly.com/) diff --git a/java/wipe_appwrite_collection/deps.gradle b/java/collection_wiper/deps.gradle similarity index 53% rename from java/wipe_appwrite_collection/deps.gradle rename to java/collection_wiper/deps.gradle index 16206c71..15af207c 100644 --- a/java/wipe_appwrite_collection/deps.gradle +++ b/java/collection_wiper/deps.gradle @@ -1,4 +1,4 @@ dependencies { implementation 'com.google.code.gson:gson:2.9.0' - implementation 'commons-validator:commons-validator:1.7' + implementation 'com.squareup.okhttp3:okhttp:4.9.0' } \ No newline at end of file diff --git a/java/wipe_appwrite_collection/Index.java b/java/wipe_appwrite_collection/Index.java deleted file mode 100644 index e69de29b..00000000 From 473928c950790a4e787fccfc642c6bfd87a7f66e Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Thu, 13 Jul 2023 15:52:54 -0400 Subject: [PATCH 04/11] Ricardo Part --- java/appwrite.json | 20 + java/appwrite/.env | 94 +++ java/appwrite/docker-compose.yml | 674 ++++++++++++++++++ java/collection_wiper/Index.java | 118 ++- .../AppwriteCollectionWiper/.gitignore | 3 + .../AppwriteCollectionWiper/README.md | 45 ++ .../AppwriteCollectionWiper/deps.gradle | 4 + .../AppwriteCollectionWiper/src/Index.java | 66 ++ 8 files changed, 998 insertions(+), 26 deletions(-) create mode 100644 java/appwrite.json create mode 100644 java/appwrite/.env create mode 100644 java/appwrite/docker-compose.yml create mode 100644 java/functions/AppwriteCollectionWiper/.gitignore create mode 100644 java/functions/AppwriteCollectionWiper/README.md create mode 100644 java/functions/AppwriteCollectionWiper/deps.gradle create mode 100644 java/functions/AppwriteCollectionWiper/src/Index.java diff --git a/java/appwrite.json b/java/appwrite.json new file mode 100644 index 00000000..6d62c7f0 --- /dev/null +++ b/java/appwrite.json @@ -0,0 +1,20 @@ +{ + "projectId": "649f0fde61b9f6d9d83c", + "projectName": "CodeDay Open Source", + "functions": [ + { + "$id": "64b036a92b2e743106ca", + "name": "AppwriteCollectionWiper", + "runtime": "java-17.0", + "path": "functions/AppwriteCollectionWiper", + "entrypoint": "src/Index.java", + "ignore": [ + "build" + ], + "execute": [], + "events": [], + "schedule": "", + "timeout": 15 + } + ] +} \ No newline at end of file diff --git a/java/appwrite/.env b/java/appwrite/.env new file mode 100644 index 00000000..c1074cb4 --- /dev/null +++ b/java/appwrite/.env @@ -0,0 +1,94 @@ +_APP_ENV=production +_APP_LOCALE=en +_APP_OPTIONS_ABUSE=enabled +_APP_OPTIONS_FORCE_HTTPS=disabled +_APP_OPENSSL_KEY_V1=Rik +_APP_DOMAIN=localhost +_APP_DOMAIN_TARGET=localhost +_APP_CONSOLE_WHITELIST_ROOT=enabled +_APP_CONSOLE_WHITELIST_EMAILS= +_APP_CONSOLE_WHITELIST_IPS= +_APP_SYSTEM_EMAIL_NAME=Appwrite +_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io +_APP_SYSTEM_RESPONSE_FORMAT= +_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io +_APP_USAGE_STATS=enabled +_APP_LOGGING_PROVIDER= +_APP_LOGGING_CONFIG= +_APP_USAGE_AGGREGATION_INTERVAL=30 +_APP_USAGE_TIMESERIES_INTERVAL=30 +_APP_USAGE_DATABASE_INTERVAL=900 +_APP_WORKER_PER_CORE=6 +_APP_REDIS_HOST=redis +_APP_REDIS_PORT=6379 +_APP_REDIS_USER= +_APP_REDIS_PASS= +_APP_DB_HOST=mariadb +_APP_DB_PORT=3306 +_APP_DB_SCHEMA=appwrite +_APP_DB_USER=user +_APP_DB_PASS=password +_APP_DB_ROOT_PASS=rootsecretpassword +_APP_INFLUXDB_HOST=influxdb +_APP_INFLUXDB_PORT=8086 +_APP_STATSD_HOST=telegraf +_APP_STATSD_PORT=8125 +_APP_SMTP_HOST= +_APP_SMTP_PORT= +_APP_SMTP_SECURE= +_APP_SMTP_USERNAME= +_APP_SMTP_PASSWORD= +_APP_SMS_PROVIDER= +_APP_SMS_FROM= +_APP_STORAGE_LIMIT=30000000 +_APP_STORAGE_PREVIEW_LIMIT=20000000 +_APP_STORAGE_ANTIVIRUS=disabled +_APP_STORAGE_ANTIVIRUS_HOST=clamav +_APP_STORAGE_ANTIVIRUS_PORT=3310 +_APP_STORAGE_DEVICE=local +_APP_STORAGE_S3_ACCESS_KEY= +_APP_STORAGE_S3_SECRET= +_APP_STORAGE_S3_REGION=us-east-1 +_APP_STORAGE_S3_BUCKET= +_APP_STORAGE_DO_SPACES_ACCESS_KEY= +_APP_STORAGE_DO_SPACES_SECRET= +_APP_STORAGE_DO_SPACES_REGION=us-east-1 +_APP_STORAGE_DO_SPACES_BUCKET= +_APP_STORAGE_BACKBLAZE_ACCESS_KEY= +_APP_STORAGE_BACKBLAZE_SECRET= +_APP_STORAGE_BACKBLAZE_REGION=us-west-004 +_APP_STORAGE_BACKBLAZE_BUCKET= +_APP_STORAGE_LINODE_ACCESS_KEY= +_APP_STORAGE_LINODE_SECRET= +_APP_STORAGE_LINODE_REGION=eu-central-1 +_APP_STORAGE_LINODE_BUCKET= +_APP_STORAGE_WASABI_ACCESS_KEY= +_APP_STORAGE_WASABI_SECRET= +_APP_STORAGE_WASABI_REGION=eu-central-1 +_APP_STORAGE_WASABI_BUCKET= +_APP_FUNCTIONS_SIZE_LIMIT=30000000 +_APP_FUNCTIONS_TIMEOUT=900 +_APP_FUNCTIONS_BUILD_TIMEOUT=900 +_APP_FUNCTIONS_CONTAINERS=10 +_APP_FUNCTIONS_CPUS=0 +_APP_FUNCTIONS_MEMORY=0 +_APP_FUNCTIONS_MEMORY_SWAP=0 +_APP_FUNCTIONS_RUNTIMES=php-8.0,python-3.9,ruby-3.0,java-17.0 +_APP_EXECUTOR_SECRET=your-secret-key +_APP_EXECUTOR_HOST=http://appwrite-executor/v1 +_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes +_APP_FUNCTIONS_ENVS=php-7.4,python-3.9,ruby-3.0,java-17.0 +_APP_FUNCTIONS_INACTIVE_THRESHOLD=60 +DOCKERHUB_PULL_USERNAME= +DOCKERHUB_PULL_PASSWORD= +DOCKERHUB_PULL_EMAIL= +OPEN_RUNTIMES_NETWORK=appwrite_runtimes +_APP_MAINTENANCE_INTERVAL=86400 +_APP_MAINTENANCE_RETENTION_CACHE=2592000 +_APP_MAINTENANCE_RETENTION_EXECUTION=1209600 +_APP_MAINTENANCE_RETENTION_AUDIT=1209600 +_APP_MAINTENANCE_RETENTION_ABUSE=86400 +_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000 +_APP_GRAPHQL_MAX_BATCH_SIZE=10 +_APP_GRAPHQL_MAX_COMPLEXITY=250 +_APP_GRAPHQL_MAX_DEPTH=3 diff --git a/java/appwrite/docker-compose.yml b/java/appwrite/docker-compose.yml new file mode 100644 index 00000000..d456023c --- /dev/null +++ b/java/appwrite/docker-compose.yml @@ -0,0 +1,674 @@ +x-logging: &x-logging + logging: + driver: 'json-file' + options: + max-file: '5' + max-size: '10m' +version: '3' + +services: + traefik: + image: traefik:2.7 + container_name: appwrite-traefik + <<: *x-logging + command: + - --providers.file.directory=/storage/config + - --providers.file.watch=true + - --providers.docker=true + - --providers.docker.exposedByDefault=false + - --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`) + - --entrypoints.appwrite_web.address=:80 + - --entrypoints.appwrite_websecure.address=:443 + restart: unless-stopped + ports: + - 80:80 + - 443:443 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - appwrite-config:/storage/config:ro + - appwrite-certificates:/storage/certificates:ro + depends_on: + - appwrite + networks: + - gateway + - appwrite + + appwrite: + image: appwrite/appwrite:1.3.7 + container_name: appwrite + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + labels: + - traefik.enable=true + - traefik.constraint-label-stack=appwrite + - traefik.docker.network=appwrite + - traefik.http.services.appwrite_api.loadbalancer.server.port=80 + #http + - traefik.http.routers.appwrite_api_http.entrypoints=appwrite_web + - traefik.http.routers.appwrite_api_http.rule=PathPrefix(`/`) + - traefik.http.routers.appwrite_api_http.service=appwrite_api + # https + - traefik.http.routers.appwrite_api_https.entrypoints=appwrite_websecure + - traefik.http.routers.appwrite_api_https.rule=PathPrefix(`/`) + - traefik.http.routers.appwrite_api_https.service=appwrite_api + - traefik.http.routers.appwrite_api_https.tls=true + volumes: + - appwrite-uploads:/storage/uploads:rw + - appwrite-cache:/storage/cache:rw + - appwrite-config:/storage/config:rw + - appwrite-certificates:/storage/certificates:rw + - appwrite-functions:/storage/functions:rw + depends_on: + - mariadb + - redis +# - clamav + - influxdb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_LOCALE + - _APP_CONSOLE_WHITELIST_ROOT + - _APP_CONSOLE_WHITELIST_EMAILS + - _APP_CONSOLE_WHITELIST_IPS + - _APP_SYSTEM_EMAIL_NAME + - _APP_SYSTEM_EMAIL_ADDRESS + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_SYSTEM_RESPONSE_FORMAT + - _APP_OPTIONS_ABUSE + - _APP_OPTIONS_FORCE_HTTPS + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_SMTP_HOST + - _APP_SMTP_PORT + - _APP_SMTP_SECURE + - _APP_SMTP_USERNAME + - _APP_SMTP_PASSWORD + - _APP_USAGE_STATS + - _APP_INFLUXDB_HOST + - _APP_INFLUXDB_PORT + - _APP_STORAGE_LIMIT + - _APP_STORAGE_PREVIEW_LIMIT + - _APP_STORAGE_ANTIVIRUS + - _APP_STORAGE_ANTIVIRUS_HOST + - _APP_STORAGE_ANTIVIRUS_PORT + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + - _APP_FUNCTIONS_SIZE_LIMIT + - _APP_FUNCTIONS_TIMEOUT + - _APP_FUNCTIONS_BUILD_TIMEOUT + - _APP_FUNCTIONS_CONTAINERS + - _APP_FUNCTIONS_CPUS + - _APP_FUNCTIONS_MEMORY + - _APP_FUNCTIONS_MEMORY_SWAP + - _APP_FUNCTIONS_RUNTIMES + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_STATSD_HOST + - _APP_STATSD_PORT + - _APP_MAINTENANCE_INTERVAL + - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_MAINTENANCE_RETENTION_CACHE + - _APP_MAINTENANCE_RETENTION_ABUSE + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY + - _APP_SMS_PROVIDER + - _APP_SMS_FROM + - _APP_GRAPHQL_MAX_BATCH_SIZE + - _APP_GRAPHQL_MAX_COMPLEXITY + - _APP_GRAPHQL_MAX_DEPTH + + appwrite-realtime: + image: appwrite/appwrite:1.3.7 + entrypoint: realtime + container_name: appwrite-realtime + <<: *x-logging + restart: unless-stopped + labels: + - "traefik.enable=true" + - "traefik.constraint-label-stack=appwrite" + - "traefik.docker.network=appwrite" + - "traefik.http.services.appwrite_realtime.loadbalancer.server.port=80" + #ws + - traefik.http.routers.appwrite_realtime_ws.entrypoints=appwrite_web + - traefik.http.routers.appwrite_realtime_ws.rule=PathPrefix(`/v1/realtime`) + - traefik.http.routers.appwrite_realtime_ws.service=appwrite_realtime + # wss + - traefik.http.routers.appwrite_realtime_wss.entrypoints=appwrite_websecure + - traefik.http.routers.appwrite_realtime_wss.rule=PathPrefix(`/v1/realtime`) + - traefik.http.routers.appwrite_realtime_wss.service=appwrite_realtime + - traefik.http.routers.appwrite_realtime_wss.tls=true + - traefik.http.routers.appwrite_realtime_wss.tls.certresolver=dns + networks: + - appwrite + depends_on: + - mariadb + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_OPTIONS_ABUSE + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_USAGE_STATS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-audits: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-audits + <<: *x-logging + container_name: appwrite-worker-audits + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-webhooks: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-webhooks + <<: *x-logging + container_name: appwrite-worker-webhooks + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-deletes: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-deletes + <<: *x-logging + container_name: appwrite-worker-deletes + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + volumes: + - appwrite-uploads:/storage/uploads:rw + - appwrite-cache:/storage/cache:rw + - appwrite-functions:/storage/functions:rw + - appwrite-builds:/storage/builds:rw + - appwrite-certificates:/storage/certificates:rw + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + + appwrite-worker-databases: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-databases + <<: *x-logging + container_name: appwrite-worker-databases + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-builds: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-builds + <<: *x-logging + container_name: appwrite-worker-builds + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-certificates: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-certificates + <<: *x-logging + container_name: appwrite-worker-certificates + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + volumes: + - appwrite-config:/storage/config:rw + - appwrite-certificates:/storage/certificates:rw + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-functions: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-functions + <<: *x-logging + container_name: appwrite-worker-functions + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + - mariadb + - appwrite-executor + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_FUNCTIONS_TIMEOUT + - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_HOST + - _APP_USAGE_STATS + - DOCKERHUB_PULL_USERNAME + - DOCKERHUB_PULL_PASSWORD + + appwrite-executor: + image: appwrite/appwrite:1.3.7 + entrypoint: executor + <<: *x-logging + container_name: appwrite-executor + restart: unless-stopped + stop_signal: SIGINT + networks: + appwrite: + runtimes: + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - appwrite-functions:/storage/functions:rw + - appwrite-builds:/storage/builds:rw + - /tmp:/tmp:rw + depends_on: + - redis + - mariadb + - appwrite + environment: + - _APP_ENV + - _APP_VERSION + - _APP_FUNCTIONS_TIMEOUT + - _APP_FUNCTIONS_BUILD_TIMEOUT + - _APP_FUNCTIONS_CONTAINERS + - _APP_FUNCTIONS_RUNTIMES + - _APP_FUNCTIONS_CPUS + - _APP_FUNCTIONS_MEMORY + - _APP_FUNCTIONS_MEMORY_SWAP + - _APP_FUNCTIONS_INACTIVE_THRESHOLD + - _APP_EXECUTOR_SECRET + - OPEN_RUNTIMES_NETWORK + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_STORAGE_DEVICE + - _APP_STORAGE_S3_ACCESS_KEY + - _APP_STORAGE_S3_SECRET + - _APP_STORAGE_S3_REGION + - _APP_STORAGE_S3_BUCKET + - _APP_STORAGE_DO_SPACES_ACCESS_KEY + - _APP_STORAGE_DO_SPACES_SECRET + - _APP_STORAGE_DO_SPACES_REGION + - _APP_STORAGE_DO_SPACES_BUCKET + - _APP_STORAGE_BACKBLAZE_ACCESS_KEY + - _APP_STORAGE_BACKBLAZE_SECRET + - _APP_STORAGE_BACKBLAZE_REGION + - _APP_STORAGE_BACKBLAZE_BUCKET + - _APP_STORAGE_LINODE_ACCESS_KEY + - _APP_STORAGE_LINODE_SECRET + - _APP_STORAGE_LINODE_REGION + - _APP_STORAGE_LINODE_BUCKET + - _APP_STORAGE_WASABI_ACCESS_KEY + - _APP_STORAGE_WASABI_SECRET + - _APP_STORAGE_WASABI_REGION + - _APP_STORAGE_WASABI_BUCKET + - DOCKERHUB_PULL_USERNAME + - DOCKERHUB_PULL_PASSWORD + + appwrite-worker-mails: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-mails + <<: *x-logging + container_name: appwrite-worker-mails + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_SYSTEM_EMAIL_NAME + - _APP_SYSTEM_EMAIL_ADDRESS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_SMTP_HOST + - _APP_SMTP_PORT + - _APP_SMTP_SECURE + - _APP_SMTP_USERNAME + - _APP_SMTP_PASSWORD + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-worker-messaging: + image: appwrite/appwrite:1.3.7 + entrypoint: worker-messaging + <<: *x-logging + container_name: appwrite-worker-messaging + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_SMS_PROVIDER + - _APP_SMS_FROM + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-maintenance: + image: appwrite/appwrite:1.3.7 + entrypoint: maintenance + <<: *x-logging + container_name: appwrite-maintenance + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_MAINTENANCE_INTERVAL + - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_MAINTENANCE_RETENTION_CACHE + - _APP_MAINTENANCE_RETENTION_ABUSE + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY + + appwrite-usage: + image: appwrite/appwrite:1.3.7 + entrypoint: usage + container_name: appwrite-usage + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + depends_on: + - influxdb + - mariadb + environment: + - _APP_ENV + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_INFLUXDB_HOST + - _APP_INFLUXDB_PORT + - _APP_USAGE_AGGREGATION_INTERVAL + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + + appwrite-schedule: + image: appwrite/appwrite:1.3.7 + entrypoint: schedule + container_name: appwrite-schedule + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + depends_on: + - redis + environment: + - _APP_ENV + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + + mariadb: + image: mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p + container_name: appwrite-mariadb + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + volumes: + - appwrite-mariadb:/var/lib/mysql:rw + environment: + - MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS} + - MYSQL_DATABASE=${_APP_DB_SCHEMA} + - MYSQL_USER=${_APP_DB_USER} + - MYSQL_PASSWORD=${_APP_DB_PASS} + command: 'mysqld --innodb-flush-method=fsync' + + redis: + image: redis:7.0.4-alpine + container_name: appwrite-redis + <<: *x-logging + restart: unless-stopped + command: > + redis-server + --maxmemory 512mb + --maxmemory-policy allkeys-lru + --maxmemory-samples 5 + networks: + - appwrite + volumes: + - appwrite-redis:/data:rw + + # clamav: + # image: appwrite/clamav:1.2.0 + # container_name: appwrite-clamav + # restart: unless-stopped + # networks: + # - appwrite + # volumes: + # - appwrite-uploads:/storage/uploads + + influxdb: + image: appwrite/influxdb:1.5.0 + container_name: appwrite-influxdb + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + volumes: + - appwrite-influxdb:/var/lib/influxdb:rw + + telegraf: + image: appwrite/telegraf:1.4.0 + container_name: appwrite-telegraf + <<: *x-logging + restart: unless-stopped + networks: + - appwrite + environment: + - _APP_INFLUXDB_HOST + - _APP_INFLUXDB_PORT + +networks: + gateway: + appwrite: + runtimes: + +volumes: + appwrite-mariadb: + appwrite-redis: + appwrite-cache: + appwrite-uploads: + appwrite-certificates: + appwrite-functions: + appwrite-builds: + appwrite-influxdb: + appwrite-config: + appwrite-executor: diff --git a/java/collection_wiper/Index.java b/java/collection_wiper/Index.java index 7c85d445..62a4c56a 100644 --- a/java/collection_wiper/Index.java +++ b/java/collection_wiper/Index.java @@ -1,36 +1,102 @@ -package java.collection_wiper; -import okhttp3.*; -import java.io.IOException; +import io.appwrite.Client; +import io.appwrite.services.Databases; +import io.appwrite.services.Exceptions.AppwriteException; +import io.appwrite.services.Models.DocumentList; +import io.appwrite.services.Response; -public AppwriteCollectionWiper { - private static final String API_ENDPOINT = "http://localhost/v1"; - private static final String PROJECT_ID = "649f0fde61b9f6d9d83c"; - private static final String COLLECTION_ID = ""; - private static final String API_KEY = "9761bd7ab2d242e1e1343cf2757e51a2f28befda464a168947f308fca1cf4d98f4d749b90291ff3d35155025018c856aeaf3d597cb1ec6ad7ce067b0d10e87eb586b2f9ca3e0da9c81a8509acdefae6c2632f95ea4f6986bdaffe8a8dc15eaa40332ff7fd059b00f6aad1ef92618a903aa7b6b273903e3c750296b75d227b182"; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +public class Index { public static void main(String[] args) { - wipeAppwriteCollection(); - } + String endpoint = System.getenv("APPWRITE_FUNCTION_ENDPOINT"); + String apiKey = System.getenv("APPWRITE_FUNCTION_API_KEY"); + String projectId = System.getenv("APPWRITE_FUNCTION_PROJECT_ID"); + + if (endpoint == null || apiKey == null || projectId == null) { + System.out.println("{\"success\": false, \"message\": \"Variables missing.\"}"); + return; + } - public static void wipeAppwriteCollection() { - OkHttpClient client = new OkHttpClient(); - Request request = new Request.Builder() - .url(API_ENDPOINT + "/database/collections/" + COLLECTION_ID + "/documents") - .addHeader("X-Appwrite-Project", PROJECT_ID) - .addHeader("X-Appwrite-Key", API_KEY) - .delete() - .build(); + Client client = new Client(); + client + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); + + Databases databases = new Databases(client); - Call call = client.newCall(request); try { - Response response = call.execute(); - if (response.isSuccessful()) { - System.out.println("Collection wiped successfully."); - } else { - System.out.println("Failed to wipe collection. Error: " + response.body().string()); + JsonObject payload = JsonParser.parseString("{}").getAsJsonObject(); + if (!payload.has("databaseId") || !payload.has("collectionId")) { + System.out.println("{\"success\": false, \"message\": \"Invalid payload.\"}"); + return; } - } catch (IOException e) { - System.out.println("An error occurred: " + e.getMessage()); + + int sum = 0; + boolean done = false; + + while (!done) { + Response response = databases.listDocuments( + payload.get("databaseId").getAsString(), + payload.get("collectionId").getAsString() + ).execute(); + + if (response.getStatusCode() != 200) { + throw new AppwriteException("Failed to list documents"); + } + + DocumentList result = response.getBody(); + + if (result == null || result.getDocuments() == null) { + done = true; + break; + } + + for (JsonObject document : result.getDocuments()) { + Response deleteResponse = databases.deleteDocument( + payload.get("databaseId").getAsString(), + payload.get("collectionId").getAsString(), + document.get("$id").getAsString() + ).execute(); + + if (deleteResponse.getStatusCode() == 200) { + sum++; + } else { + throw new AppwriteException("Failed to delete document"); + } + } + + if (result.getDocuments().size() == 0) { + done = true; + } + } + + System.out.println("{\"success\": true, \"sum\": " + sum + "}"); + } catch (AppwriteException e) { + System.out.println("{\"success\": false, \"message\": \"Unexpected error: " + e.getMessage() + "\"}"); } } } + +/** + * This function will validate that the payload and variables are non-empty in the request + * + * @param req is the received POST request + * @return null is nothing is empty, otherwise an error response + */ +private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req,RuntimeResponse res){ + Map responseData=new HashMap<>(); + + if(req.getPayload().isEmpty()||req.getPayload().trim().equals("{}")){ + responseData.put("message","Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + } + + if(req.getVariables()==null){ + responseData.put("success",false); + responseData.put("message","Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + return null; +} \ No newline at end of file diff --git a/java/functions/AppwriteCollectionWiper/.gitignore b/java/functions/AppwriteCollectionWiper/.gitignore new file mode 100644 index 00000000..8d482b58 --- /dev/null +++ b/java/functions/AppwriteCollectionWiper/.gitignore @@ -0,0 +1,3 @@ +# OS +## Mac +.DS_Store diff --git a/java/functions/AppwriteCollectionWiper/README.md b/java/functions/AppwriteCollectionWiper/README.md new file mode 100644 index 00000000..ecbaa463 --- /dev/null +++ b/java/functions/AppwriteCollectionWiper/README.md @@ -0,0 +1,45 @@ +# AppwriteCollectionWiper + +Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file. + +## 🤖 Documentation + +Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are. + + + +_Example input:_ + +This function expects no input + + + +_Example output:_ + + + +```json +{ + "areDevelopersAwesome": true +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- No special environment variables are required for the cloud function. + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/Index.java`, and upload the file we just generated. diff --git a/java/functions/AppwriteCollectionWiper/deps.gradle b/java/functions/AppwriteCollectionWiper/deps.gradle new file mode 100644 index 00000000..4702e593 --- /dev/null +++ b/java/functions/AppwriteCollectionWiper/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'io.appwrite:sdk-for-kotlin:1.2.0' + implementation 'com.google.code.gson:gson:2.9.0' +} \ No newline at end of file diff --git a/java/functions/AppwriteCollectionWiper/src/Index.java b/java/functions/AppwriteCollectionWiper/src/Index.java new file mode 100644 index 00000000..49e2e3ab --- /dev/null +++ b/java/functions/AppwriteCollectionWiper/src/Index.java @@ -0,0 +1,66 @@ +import java.util.Map; +import java.util.HashMap; +import java.net.HttpURLConnection; +import java.net.URL; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import com.google.gson.Gson; +import io.appwrite.Client; +import io.appwrite.services.Account; +import io.appwrite.services.Avatars; +import io.appwrite.services.Databases; +import io.appwrite.services.Functions; +import io.appwrite.services.Health; +import io.appwrite.services.Locale; +import io.appwrite.services.Storage; +import io.appwrite.services.Teams; +import io.appwrite.services.Users; + +/* + 'req' variable has: + 'getHeaders()' - function to get headers as a Map + 'getPayload()' - function to get body data as a String + 'getVariables()' - function to get variables as a Map + + 'res' variable has: + 'send(text, status)' - function that accepts a String to return text response. Status code defaults to 200 + 'json(obj, status)' - function that accepts a Map to return JSON response. Status code defaults to 200 + + If an error is thrown, a response with code 500 will be returned. +*/ + +final Gson gson = new Gson(); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + var client = new Client(); + + // You can remove services you don't use + var account = new Account(client); + var avatars = new Avatars(client); + var database = new Databases(client); + var functions = new Functions(client); + var health = new Health(client); + var locale = new Locale(client); + var storage = new Storage(client); + var teams = new Teams(client); + var users = new Users(client); + + var variables = req.getVariables(); + + if (variables == null + || !variables.containsKey("APPWRITE_FUNCTION_ENDPOINT") + || !variables.containsKey("APPWRITE_FUNCTION_API_KEY") + || variables.get("APPWRITE_FUNCTION_ENDPOINT") == null + || variables.get("APPWRITE_FUNCTION_API_KEY") == null) { + System.out.println("Environment variables are not set. Function cannot use Appwrite SDK."); + } else { + client + .setEndpoint(variables.get("APPWRITE_FUNCTION_ENDPOINT")) + .setProject(variables.get("APPWRITE_FUNCTION_PROJECT_ID")) + .setKey(variables.get("APPWRITE_FUNCTION_API_KEY")); + } + + return res.json(Map.of( + "areDevelopersAwesome", true + )); +} From acdffa7b33ce225693469ac8cb7e4f0500d8b0e3 Mon Sep 17 00:00:00 2001 From: ElizabethBarco <115512791+ElizabethBarco@users.noreply.github.com> Date: Fri, 14 Jul 2023 12:13:09 -0700 Subject: [PATCH 05/11] First commit --- .idea/.gitignore | 8 ++++++++ .idea/examples.iml | 9 +++++++++ .idea/misc.xml | 6 ++++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ 5 files changed, 37 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/examples.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/examples.iml b/.idea/examples.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/.idea/examples.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..639900d1 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..704ff0e8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 4dacdcdde75cb7b7e1af2f7bcb54476b062e410d Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Mon, 24 Jul 2023 15:45:39 -0400 Subject: [PATCH 06/11] Better organized --- .../AppwriteCollectionWiper/.gitignore | 0 java/AppwriteCollectionWiper/Index.java | 96 +++++++++++++++++++ .../AppwriteCollectionWiper/README.md | 0 .../AppwriteCollectionWiper/deps.gradle | 0 java/appwrite.json | 2 +- .../AppwriteCollectionWiper/src/Index.java | 66 ------------- 6 files changed, 97 insertions(+), 67 deletions(-) rename java/{functions => }/AppwriteCollectionWiper/.gitignore (100%) create mode 100644 java/AppwriteCollectionWiper/Index.java rename java/{functions => }/AppwriteCollectionWiper/README.md (100%) rename java/{functions => }/AppwriteCollectionWiper/deps.gradle (100%) delete mode 100644 java/functions/AppwriteCollectionWiper/src/Index.java diff --git a/java/functions/AppwriteCollectionWiper/.gitignore b/java/AppwriteCollectionWiper/.gitignore similarity index 100% rename from java/functions/AppwriteCollectionWiper/.gitignore rename to java/AppwriteCollectionWiper/.gitignore diff --git a/java/AppwriteCollectionWiper/Index.java b/java/AppwriteCollectionWiper/Index.java new file mode 100644 index 00000000..78446e14 --- /dev/null +++ b/java/AppwriteCollectionWiper/Index.java @@ -0,0 +1,96 @@ +import java.util.Map; +import com.google.gson.JsonObject; +import com.google.gson.Gson; +import io.appwrite.Client; +import io.appwrite.services.Databases; +import io.appwrite.exceptions.AppwriteException; +import io.appwrite.models.DocumentList; + +final Gson gson = new Gson(); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + var client = new Client(); + var database = new Databases(client); + + var variables = req.getVariables(); + + System.out.println("In the jungle ******"); + + if (variables == null + || !variables.containsKey("APPWRITE_FUNCTION_ENDPOINT") + || !variables.containsKey("APPWRITE_FUNCTION_API_KEY") + || !variables.containsKey("APPWRITE_FUNCTION_PROJECT_ID") + || variables.get("APPWRITE_FUNCTION_ENDPOINT") == null + || variables.get("APPWRITE_FUNCTION_API_KEY") == null + || variables.get("APPWRITE_FUNCTION_PROJECT_ID") == null) { + return res.json(Map.of( + "success", false, + "message", "Variables missing." + )); + } else { + client + .setEndpoint(variables.get("APPWRITE_FUNCTION_ENDPOINT")) + .setProject(variables.get("APPWRITE_FUNCTION_PROJECT_ID")) + .setKey(variables.get("APPWRITE_FUNCTION_API_KEY")); + } + + try { + JsonObject payload = gson.fromJson(req.getPayload(), JsonObject.class); + if (!payload.has("databaseId") || !payload.has("collectionId")) { + return res.json(Map.of( + "success", false, + "message", "Invalid payload." + )); + } + + int sum = 0; + boolean done = false; + + while (!done) { + Response response = database.listDocuments( + payload.get("databaseId").getAsString(), + payload.get("collectionId").getAsString() + ).execute(); + + if (response.getStatusCode() != 200) { + throw new AppwriteException("Failed to list documents"); + } + + DocumentList result = response.getBody(); + + if (result == null || result.getDocuments() == null) { + done = true; + break; + } + + for (var document : result.getDocuments()) { + Response deleteResponse = database.deleteDocument( + payload.get("databaseId").getAsString(), + payload.get("collectionId").getAsString(), + document.get("$id").getAsString() + ).execute(); + + if (deleteResponse.getStatusCode() == 200) { + sum++; + } else { + throw new AppwriteException("Failed to delete document"); + } + } + + if (result.getDocuments().size() == 0) { + done = true; + } + } + + return res.json(Map.of( + "success", true, + "sum", sum + )); + } catch (AppwriteException e) { + return res.json(Map.of( + "success", false, + "message", "Unexpected error: " + e.getMessage() + )); + } +} + diff --git a/java/functions/AppwriteCollectionWiper/README.md b/java/AppwriteCollectionWiper/README.md similarity index 100% rename from java/functions/AppwriteCollectionWiper/README.md rename to java/AppwriteCollectionWiper/README.md diff --git a/java/functions/AppwriteCollectionWiper/deps.gradle b/java/AppwriteCollectionWiper/deps.gradle similarity index 100% rename from java/functions/AppwriteCollectionWiper/deps.gradle rename to java/AppwriteCollectionWiper/deps.gradle diff --git a/java/appwrite.json b/java/appwrite.json index 6d62c7f0..bbe45396 100644 --- a/java/appwrite.json +++ b/java/appwrite.json @@ -6,7 +6,7 @@ "$id": "64b036a92b2e743106ca", "name": "AppwriteCollectionWiper", "runtime": "java-17.0", - "path": "functions/AppwriteCollectionWiper", + "path": "AppwriteCollectionWiper", "entrypoint": "src/Index.java", "ignore": [ "build" diff --git a/java/functions/AppwriteCollectionWiper/src/Index.java b/java/functions/AppwriteCollectionWiper/src/Index.java deleted file mode 100644 index 49e2e3ab..00000000 --- a/java/functions/AppwriteCollectionWiper/src/Index.java +++ /dev/null @@ -1,66 +0,0 @@ -import java.util.Map; -import java.util.HashMap; -import java.net.HttpURLConnection; -import java.net.URL; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import com.google.gson.Gson; -import io.appwrite.Client; -import io.appwrite.services.Account; -import io.appwrite.services.Avatars; -import io.appwrite.services.Databases; -import io.appwrite.services.Functions; -import io.appwrite.services.Health; -import io.appwrite.services.Locale; -import io.appwrite.services.Storage; -import io.appwrite.services.Teams; -import io.appwrite.services.Users; - -/* - 'req' variable has: - 'getHeaders()' - function to get headers as a Map - 'getPayload()' - function to get body data as a String - 'getVariables()' - function to get variables as a Map - - 'res' variable has: - 'send(text, status)' - function that accepts a String to return text response. Status code defaults to 200 - 'json(obj, status)' - function that accepts a Map to return JSON response. Status code defaults to 200 - - If an error is thrown, a response with code 500 will be returned. -*/ - -final Gson gson = new Gson(); - -public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { - var client = new Client(); - - // You can remove services you don't use - var account = new Account(client); - var avatars = new Avatars(client); - var database = new Databases(client); - var functions = new Functions(client); - var health = new Health(client); - var locale = new Locale(client); - var storage = new Storage(client); - var teams = new Teams(client); - var users = new Users(client); - - var variables = req.getVariables(); - - if (variables == null - || !variables.containsKey("APPWRITE_FUNCTION_ENDPOINT") - || !variables.containsKey("APPWRITE_FUNCTION_API_KEY") - || variables.get("APPWRITE_FUNCTION_ENDPOINT") == null - || variables.get("APPWRITE_FUNCTION_API_KEY") == null) { - System.out.println("Environment variables are not set. Function cannot use Appwrite SDK."); - } else { - client - .setEndpoint(variables.get("APPWRITE_FUNCTION_ENDPOINT")) - .setProject(variables.get("APPWRITE_FUNCTION_PROJECT_ID")) - .setKey(variables.get("APPWRITE_FUNCTION_API_KEY")); - } - - return res.json(Map.of( - "areDevelopersAwesome", true - )); -} From ced70bdd686763bb757d197a0058b6c67ced31b7 Mon Sep 17 00:00:00 2001 From: ricardonunezlopez Date: Mon, 24 Jul 2023 15:48:14 -0400 Subject: [PATCH 07/11] Better organized --- .idea/.gitignore | 8 ++++++++ .idea/compiler.xml | 8 ++++++++ .idea/examples.iml | 9 +++++++++ .idea/gradle.xml | 17 +++++++++++++++++ .idea/jarRepositories.xml | 20 ++++++++++++++++++++ .idea/misc.xml | 8 ++++++++ .idea/modules.xml | 8 ++++++++ .idea/runConfigurations/Run.xml | 21 +++++++++++++++++++++ .idea/vcs.xml | 6 ++++++ 9 files changed, 105 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/examples.iml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations/Run.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..7c883b63 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/examples.iml b/.idea/examples.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/.idea/examples.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..9a13d784 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..fdc392fe --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..04593815 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..704ff0e8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Run.xml b/.idea/runConfigurations/Run.xml new file mode 100644 index 00000000..de1f5de1 --- /dev/null +++ b/.idea/runConfigurations/Run.xml @@ -0,0 +1,21 @@ + + + + + + + true + true + false + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 32fb181ebaad049b1db85626c9488da3520f4563 Mon Sep 17 00:00:00 2001 From: lipinggm Date: Sat, 29 Jul 2023 00:07:26 -0400 Subject: [PATCH 08/11] Sample code as reference --- java/collection_wiper/Index.java | 152 ++++++++++++++++-------------- java/collection_wiper/README.md | 40 +------- java/collection_wiper/deps.gradle | 4 + 3 files changed, 88 insertions(+), 108 deletions(-) diff --git a/java/collection_wiper/Index.java b/java/collection_wiper/Index.java index 62a4c56a..32f3eaa5 100644 --- a/java/collection_wiper/Index.java +++ b/java/collection_wiper/Index.java @@ -1,81 +1,84 @@ import io.appwrite.Client; import io.appwrite.services.Databases; -import io.appwrite.services.Exceptions.AppwriteException; -import io.appwrite.services.Models.DocumentList; -import io.appwrite.services.Response; +import io.appwrite.exceptions.AppwriteException; +import io.appwrite.models.DocumentList; +import kotlin.Result; +import kotlin.coroutines.Continuation; +import kotlin.coroutines.CoroutineContext; +import kotlin.coroutines.EmptyCoroutineContext; +import okhttp3.Response; +import org.jetbrains.annotations.NotNull; +import io.openruntimes.java.*; +import java.util.*; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -public class Index { - public static void main(String[] args) { - String endpoint = System.getenv("APPWRITE_FUNCTION_ENDPOINT"); - String apiKey = System.getenv("APPWRITE_FUNCTION_API_KEY"); - String projectId = System.getenv("APPWRITE_FUNCTION_PROJECT_ID"); - - if (endpoint == null || apiKey == null || projectId == null) { - System.out.println("{\"success\": false, \"message\": \"Variables missing.\"}"); - return; - } - - Client client = new Client(); - client - .setEndpoint(endpoint) - .setProject(projectId) - .setKey(apiKey); - - Databases databases = new Databases(client); - - try { - JsonObject payload = JsonParser.parseString("{}").getAsJsonObject(); - if (!payload.has("databaseId") || !payload.has("collectionId")) { - System.out.println("{\"success\": false, \"message\": \"Invalid payload.\"}"); - return; - } - - int sum = 0; - boolean done = false; +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { + // Validate that values present in the request are not empty (payload, variables) + RuntimeResponse errorResponse=checkEmptyPayloadAndVariables(req,res); + if(errorResponse!=null){ + return errorResponse; + } + String endpoint = req.getVariables().get("APPWRITE_FUNCTION_ENDPOINT"); + String apiKey = req.getVariables().get("APPWRITE_FUNCTION_API_KEY"); + String projectId = req.getVariables().get("APPWRITE_FUNCTION_PROJECT_ID"); - while (!done) { - Response response = databases.listDocuments( - payload.get("databaseId").getAsString(), - payload.get("collectionId").getAsString() - ).execute(); + Map responseData=new HashMap<>(); + if (endpoint == null || apiKey == null || projectId == null) { + responseData.put("success",false); + responseData.put("message","Variables missing."); + return res.json(responseData); + } - if (response.getStatusCode() != 200) { - throw new AppwriteException("Failed to list documents"); - } + Client client = new Client(); + client + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey); - DocumentList result = response.getBody(); + Databases databases = new Databases(client); - if (result == null || result.getDocuments() == null) { - done = true; - break; + try { + JsonObject payload = JsonParser.parseString("{}").getAsJsonObject(); + if (!payload.has("databaseId") || !payload.has("collectionId")) { + responseData.put("success",false); + responseData.put("message","Invalid payload."); + return res.json(responseData); + } + databases.deleteCollection( + payload.get("databaseId").getAsString(), + payload.get("collectionId").getAsString(), + new Continuation() { + @NotNull + @Override + public CoroutineContext getContext() { + return EmptyCoroutineContext.INSTANCE; } - for (JsonObject document : result.getDocuments()) { - Response deleteResponse = databases.deleteDocument( - payload.get("databaseId").getAsString(), - payload.get("collectionId").getAsString(), - document.get("$id").getAsString() - ).execute(); - - if (deleteResponse.getStatusCode() == 200) { - sum++; - } else { - throw new AppwriteException("Failed to delete document"); + @Override + public void resumeWith(@NotNull Object o) { + String json = ""; + try { + if (o instanceof Result.Failure) { + Result.Failure failure = (Result.Failure) o; + throw failure.exception; + } else { + Response response = (Response) o; + } + } catch (Throwable th) { + System.out.println("ERROR: " + th.toString()); } } - - if (result.getDocuments().size() == 0) { - done = true; - } } + ); - System.out.println("{\"success\": true, \"sum\": " + sum + "}"); - } catch (AppwriteException e) { - System.out.println("{\"success\": false, \"message\": \"Unexpected error: " + e.getMessage() + "\"}"); - } + responseData.put("success",true); + return res.json(responseData); + } catch (AppwriteException e) { + responseData.put("success",true); + responseData.put("message","Unexpected error: " + e.getMessage()); + return res.json(responseData); } } @@ -86,17 +89,20 @@ public static void main(String[] args) { * @return null is nothing is empty, otherwise an error response */ private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req,RuntimeResponse res){ - Map responseData=new HashMap<>(); - if(req.getPayload().isEmpty()||req.getPayload().trim().equals("{}")){ - responseData.put("message","Payload is empty, expected a payload with provider and URL"); - return res.json(responseData); - } + Map responseData=new HashMap<>(); - if(req.getVariables()==null){ - responseData.put("success",false); - responseData.put("message","Empty function variables found. You need to pass an API key for the provider"); - return res.json(responseData); - } - return null; + if(req.getPayload()==null||req.getPayload().trim().isEmpty()||req.getPayload().trim().equals("{}")){ + responseData.put("success",false); + responseData.put("message","Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + + } + if(req.getVariables()==null){ + responseData.put("success",false); + responseData.put("message","Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + + return null; } \ No newline at end of file diff --git a/java/collection_wiper/README.md b/java/collection_wiper/README.md index aaa422c1..e4046266 100644 --- a/java/collection_wiper/README.md +++ b/java/collection_wiper/README.md @@ -9,50 +9,20 @@ _Bitly Example input:_ ```json -{ - "provider": "bitly", - "url": "https://google.com" -} +{"databaseId":"stage","collectionId":"profiles"} ``` -_Bitly Example output:_ +_Example output:_ ```json -{ - "success": true, - "url": "https://bit.ly/3CywbjA" -} -``` - -_Tinyurl Example input:_ - - - -```json -{ - "provider": "tinyurl", - "url": "https://google.com" -} -``` - -_Tinyurl Example output:_ - - -```json -{ - "success": true, - "url": "https://tinyurl.com/dck67zxk" -} +{"success":true} ``` _Error Example output:_ ```json -{ - "success": false, - "message":"Provided URL: https://xyz is not valid, please provide a valid, correctly formed URL" -} +{"success":false,"message":"Collection not found."} ``` @@ -75,7 +45,7 @@ $ cd java/short_url_generator 2. Enter this function folder and build the code: ``` -docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm -it -v ${PWD}:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh ``` As a result, a `code.tar.gz` file will be generated. diff --git a/java/collection_wiper/deps.gradle b/java/collection_wiper/deps.gradle index 15af207c..68565d1e 100644 --- a/java/collection_wiper/deps.gradle +++ b/java/collection_wiper/deps.gradle @@ -1,4 +1,8 @@ dependencies { implementation 'com.google.code.gson:gson:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.0' + implementation 'io.appwrite:sdk-for-kotlin:1.2.0' + implementation "org.rapidoid:rapidoid-http-server:5.5.5" + implementation 'org.bstats:bstats-bukkit:2.2.1' + implementation 'org.jetbrains.kotlin:kotlin-script-runtime:1.9.0' } \ No newline at end of file From ce468a1c756c4adeb63d2df1f7772439234d8c91 Mon Sep 17 00:00:00 2001 From: Elizabeth Barco Date: Mon, 7 Aug 2023 19:44:58 +0000 Subject: [PATCH 09/11] collection_wiper_elizabeth --- java/AppwriteCollectionWiper/Index.java | 142 ++++++++++++------------ 1 file changed, 69 insertions(+), 73 deletions(-) diff --git a/java/AppwriteCollectionWiper/Index.java b/java/AppwriteCollectionWiper/Index.java index 78446e14..64f7c4be 100644 --- a/java/AppwriteCollectionWiper/Index.java +++ b/java/AppwriteCollectionWiper/Index.java @@ -1,96 +1,92 @@ import java.util.Map; -import com.google.gson.JsonObject; +import java.util.HashMap; +import java.util.*; +import io.openruntimes.java.*; import com.google.gson.Gson; import io.appwrite.Client; -import io.appwrite.services.Databases; import io.appwrite.exceptions.AppwriteException; -import io.appwrite.models.DocumentList; +import io.appwrite.services.Databases; +import kotlin.Result; +import kotlin.coroutines.Continuation; +import kotlin.coroutines.CoroutineContext; +import kotlin.coroutines.EmptyCoroutineContext; +import org.jetbrains.annotations.NotNull; +import okhttp3.Response; +import com.google.gson.JsonParser; +import com.google.gson.JsonObject; final Gson gson = new Gson(); -public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { - var client = new Client(); - var database = new Databases(client); - - var variables = req.getVariables(); - System.out.println("In the jungle ******"); - - if (variables == null +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + + + + // Initialize the Appwrite client and databases service + var client = new Client(); + var databases = new Databases(client); + var variables = req.getVariables(); + var payloadString = req.getPayload(); + + // Check if the required environment variables are set + if (variables == null || !variables.containsKey("APPWRITE_FUNCTION_ENDPOINT") || !variables.containsKey("APPWRITE_FUNCTION_API_KEY") || !variables.containsKey("APPWRITE_FUNCTION_PROJECT_ID") || variables.get("APPWRITE_FUNCTION_ENDPOINT") == null || variables.get("APPWRITE_FUNCTION_API_KEY") == null || variables.get("APPWRITE_FUNCTION_PROJECT_ID") == null) { - return res.json(Map.of( - "success", false, - "message", "Variables missing." - )); - } else { - client + return res.json(Map.of("Environment variables are not set. Function cannot use Appwrite SDK.", false)); + } else { + // Set the Appwrite client properties + client .setEndpoint(variables.get("APPWRITE_FUNCTION_ENDPOINT")) .setProject(variables.get("APPWRITE_FUNCTION_PROJECT_ID")) .setKey(variables.get("APPWRITE_FUNCTION_API_KEY")); + } + + try { + // Parse the payload data into a Map + + Map payload = gson.fromJson(payloadString, Map.class); + String databaseId = (String) payload.get("databaseId"); + String collectionId = (String) payload.get("collectionId"); + if (payload == null || databaseId == null || collectionId == null) { + return res.json(Map.of("Invalid payload.", false)); } - - try { - JsonObject payload = gson.fromJson(req.getPayload(), JsonObject.class); - if (!payload.has("databaseId") || !payload.has("collectionId")) { - return res.json(Map.of( - "success", false, - "message", "Invalid payload." - )); - } - - int sum = 0; - boolean done = false; - - while (!done) { - Response response = database.listDocuments( - payload.get("databaseId").getAsString(), - payload.get("collectionId").getAsString() - ).execute(); - - if (response.getStatusCode() != 200) { - throw new AppwriteException("Failed to list documents"); - } - - DocumentList result = response.getBody(); - - if (result == null || result.getDocuments() == null) { - done = true; - break; - } - - for (var document : result.getDocuments()) { - Response deleteResponse = database.deleteDocument( - payload.get("databaseId").getAsString(), - payload.get("collectionId").getAsString(), - document.get("$id").getAsString() - ).execute(); - - if (deleteResponse.getStatusCode() == 200) { - sum++; - } else { - throw new AppwriteException("Failed to delete document"); + + + + databases.deleteCollection( + databaseId, + collectionId, + new Continuation() { + @NotNull + @Override + public CoroutineContext getContext() { + return EmptyCoroutineContext.INSTANCE; } - } - if (result.getDocuments().size() == 0) { - done = true; + @Override + public void resumeWith(@NotNull Object o) { + String json = ""; + try { + if (o instanceof Result.Failure) { + Result.Failure failure = (Result.Failure) o; + throw failure.exception; + } else { + Response response = (Response) o; + } + } catch (Throwable th) { + System.out.println("ERROR: " + th.toString()); + } + } } - } + ); + return res.json(Map.of("Success", true)); - return res.json(Map.of( - "success", true, - "sum", sum - )); - } catch (AppwriteException e) { - return res.json(Map.of( - "success", false, - "message", "Unexpected error: " + e.getMessage() - )); - } + }catch (AppwriteException e) { + + return res.json(Map.of("Collection not found", false)); + } } - From 29e07826f5e654c654fc95fa304880ee547a8827 Mon Sep 17 00:00:00 2001 From: lipinggm Date: Sun, 13 Aug 2023 22:39:28 -0400 Subject: [PATCH 10/11] update Index --- java/collection_wiper/Index.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/java/collection_wiper/Index.java b/java/collection_wiper/Index.java index 32f3eaa5..da6e0295 100644 --- a/java/collection_wiper/Index.java +++ b/java/collection_wiper/Index.java @@ -13,6 +13,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.Gson; public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { // Validate that values present in the request are not empty (payload, variables) @@ -24,7 +25,7 @@ public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { String apiKey = req.getVariables().get("APPWRITE_FUNCTION_API_KEY"); String projectId = req.getVariables().get("APPWRITE_FUNCTION_PROJECT_ID"); - Map responseData=new HashMap<>(); + Map responseData = new HashMap<>(); if (endpoint == null || apiKey == null || projectId == null) { responseData.put("success",false); responseData.put("message","Variables missing."); @@ -38,17 +39,21 @@ public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { .setKey(apiKey); Databases databases = new Databases(client); - + Gson gson=new Gson(); try { - JsonObject payload = JsonParser.parseString("{}").getAsJsonObject(); - if (!payload.has("databaseId") || !payload.has("collectionId")) { + String payloadString = req.getPayload().toString(); + + Map payload = gson.fromJson(payloadString, Map.class); + // Get file url from payload + + String databaseId = payload.get("databaseId"); + String collectionId = payload.get("collectionId"); + if ( databaseId == null || collectionId == null) { responseData.put("success",false); responseData.put("message","Invalid payload."); return res.json(responseData); } - databases.deleteCollection( - payload.get("databaseId").getAsString(), - payload.get("collectionId").getAsString(), + databases.deleteCollection(databaseId, collectionId, new Continuation() { @NotNull @Override From b927f6512e024ee2a9714f08d92742db892d28b5 Mon Sep 17 00:00:00 2001 From: Elizabeth Barco Date: Fri, 18 Aug 2023 19:08:29 +0000 Subject: [PATCH 11/11] collection_wiper --- java/wipe_appwrite_collection/Index.java | 86 +++++++++++++++++++++++ java/wipe_appwrite_collection/README.md | 70 ++++++++++++++++++ java/wipe_appwrite_collection/deps.gradle | 4 ++ 3 files changed, 160 insertions(+) create mode 100644 java/wipe_appwrite_collection/Index.java create mode 100644 java/wipe_appwrite_collection/README.md create mode 100644 java/wipe_appwrite_collection/deps.gradle diff --git a/java/wipe_appwrite_collection/Index.java b/java/wipe_appwrite_collection/Index.java new file mode 100644 index 00000000..9220290f --- /dev/null +++ b/java/wipe_appwrite_collection/Index.java @@ -0,0 +1,86 @@ +import java.util.Map; +import java.util.HashMap; +import java.util.*; +import io.openruntimes.java.*; +import com.google.gson.Gson; +import io.appwrite.Client; +import io.appwrite.exceptions.AppwriteException; +import io.appwrite.services.Databases; +import kotlin.Result; +import kotlin.coroutines.Continuation; +import kotlin.coroutines.CoroutineContext; +import kotlin.coroutines.EmptyCoroutineContext; +import org.jetbrains.annotations.NotNull; +import okhttp3.Response; +import com.google.gson.JsonParser; +import com.google.gson.JsonObject; + +final Gson gson = new Gson(); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + // Initialize the Appwrite client and databases service + Client client = new Client(); + var variables = req.getVariables(); + String payloadString = req.getPayload().toString(); + Map responseData = new HashMap<>(); + + // Check if the required environment variables are set + if (variables == null + || !variables.containsKey("APPWRITE_FUNCTION_ENDPOINT") + || !variables.containsKey("APPWRITE_FUNCTION_API_KEY") + || !variables.containsKey("APPWRITE_FUNCTION_PROJECT_ID") + || variables.get("APPWRITE_FUNCTION_ENDPOINT") == null + || variables.get("APPWRITE_FUNCTION_API_KEY") == null + || variables.get("APPWRITE_FUNCTION_PROJECT_ID") == null) { + return res.json(Map.of("Environment variables are not set. Function cannot use Appwrite SDK.", false)); + } else { + // Set the Appwrite client properties + client + .setEndpoint(variables.get("APPWRITE_FUNCTION_ENDPOINT")) + .setProject(variables.get("APPWRITE_FUNCTION_PROJECT_ID")) + .setKey(variables.get("APPWRITE_FUNCTION_API_KEY")); + } + + try { + // Parse the payload data into a Map + Databases databases = new Databases(client); + Map payload = gson.fromJson(payloadString, Map.class); + String databaseId = (String) payload.get("databaseId"); + String collectionId = (String) payload.get("collectionId"); + + if (databaseId == null || collectionId == null) { + return res.json(Map.of("Invalid payload.", false)); + } + + databases.deleteCollection( + databaseId, + collectionId, + new Continuation() { + @NotNull + @Override + public CoroutineContext getContext() { + return EmptyCoroutineContext.INSTANCE; + } + + @Override + public void resumeWith(@NotNull Object o) { + String json = ""; + try { + if (o instanceof Result.Failure) { + Result.Failure failure = (Result.Failure) o; + throw failure.exception; + } else { + Response response = (Response) o; + } + } catch (Throwable th) { + System.out.print("ERROR: " + th.toString()); + } + } + } + ); + + return res.json(Map.of("success", true)); + } catch (AppwriteException e) { + return res.json(Map.of("Collection not found.", false)); + } +} diff --git a/java/wipe_appwrite_collection/README.md b/java/wipe_appwrite_collection/README.md new file mode 100644 index 00000000..5398f972 --- /dev/null +++ b/java/wipe_appwrite_collection/README.md @@ -0,0 +1,70 @@ +# Appwrite Collection Wiper + +Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file. + +## 🤖 Documentation + +A Java Cloud Function that wipes all the documents inside a collection. + +_Example input:_ + +```json +{ +"databaseId": "stage", +"collectionId": "profiles" +} +``` + +_Example output (_sucess_):_ + +```json +{ +"success": true, +} +``` + +_Example output (_failure_):_ + +```json +{ +"success": false, +"message": "Collection not found." +} +``` + +## 📝 Environment Variables + + APPWRITE_FUNCTION_ENDPOINT - Endpoint of your Appwrite server + APPWRITE_FUNCTION_API_KEY - Appwrite API Key + APPWRITE_FUNCTION_PROJECT_ID - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + + $ git clone https://github.com/open-runtimes/examples.git && cd examples + $ cd java/wipe_appwrite_collection + +2. Enter this function folder and build the code: + + docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-18.0 sh /usr/local/src/build.sh + As a result, a code.tar.gz file will be generated. + +3. Start the Open Runtime: + + docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-18.0 sh /usr/local/src/start.sh + Your function is now listening on port 3000, and you can execute it by sending POST request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime README. + +4. Execute function: + + curl http://localhost:3000/ -d '{"variables":{"APPWRITE_FUNCTION_ENDPOINT":"YOUR_ENDPOINT","APPWRITE_FUNCTION_PROJECT_ID":"YOUR_PROJECT_ID","APPWRITE_FUNCTION_API_KEY":"YOUR_API_KEY"},"payload":"{\"databaseId\":\"stage\",\"collectionId\":\"profiles\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" + +### Using CLI + + Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + + Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + + Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/Index.java`, and upload the file we just generated. diff --git a/java/wipe_appwrite_collection/deps.gradle b/java/wipe_appwrite_collection/deps.gradle new file mode 100644 index 00000000..7bfc5b25 --- /dev/null +++ b/java/wipe_appwrite_collection/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'io.appwrite:sdk-for-kotlin:1.2.0' +} \ No newline at end of file