-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from appwrite/feat-port-censor-with-redact
feat: Port Censor with Redact
- Loading branch information
Showing
13 changed files
with
632 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# See https://www.dartlang.org/guides/libraries/private-files | ||
|
||
# Files and directories created by pub | ||
.dart_tool/ | ||
.packages | ||
build/ | ||
# If you're building an application, you may want to check-in your pubspec.lock | ||
pubspec.lock | ||
|
||
# Directory created by dartdoc | ||
# If you don't generate documentation locally you can remove this line. | ||
doc/api/ | ||
|
||
# dotenv environment variables file | ||
.env* | ||
|
||
# Avoid committing generated Javascript files: | ||
*.dart.js | ||
*.info.json # Produced by the --dump-info flag. | ||
*.js # When generated by dart2js. Don't specify *.js if your | ||
# project includes source files written in JavaScript. | ||
*.js_ | ||
*.js.deps | ||
*.js.map | ||
|
||
.flutter-plugins | ||
.flutter-plugins-dependencies |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# 🤐 Dart Censor with Redact Function | ||
|
||
Automatically remove sensitive data from messages. | ||
|
||
## 🧰 Usage | ||
|
||
### GET / | ||
|
||
HTML form for interacting with the function. | ||
|
||
### POST / | ||
|
||
Returns the supplied text string with sensitive information redacted. | ||
|
||
**Parameters** | ||
|
||
| Name | Description | Location | Type | Sample Value | | ||
| ------------ | --------------------------- | -------- | ------------------ | ------------------------------------------ | | ||
| Content-Type | Content type of the request | Header | `application/json` | N/A | | ||
| text | Text to redact | Body | String | `My email address is [email protected]` | | ||
|
||
**Response** | ||
|
||
Sample `200` Response: | ||
|
||
```json | ||
{ | ||
"ok": true, | ||
"redacted": "My email address is <EMAIL_ADDRESS>" | ||
} | ||
``` | ||
|
||
Sample `400` Response: | ||
|
||
```json | ||
{ | ||
"ok": false, | ||
"error": "Missing required field: text." | ||
} | ||
``` | ||
|
||
## ⚙️ Configuration | ||
|
||
| Setting | Value | | ||
| ----------------- | --------------- | | ||
| Runtime | Dart (2.17) | | ||
| Entrypoint | `lib/main.dart` | | ||
| Build Commands | `dart pub get` | | ||
| Permissions | `any` | | ||
| Timeout (Seconds) | 15 | | ||
|
||
## 🔒 Environment Variables | ||
|
||
### PANGEA_REDACT_TOKEN | ||
|
||
Access token for the Pangea Redact API | ||
|
||
| Question | Answer | | ||
| ------------- | --------------------------------------------------------------------------------------- | | ||
| Required | Yes | | ||
| Sample Value | `pts_7p4...5wl4` | | ||
| Documentation | [Pangea: Configuration](https://pangea.cloud/docs/redact/getting-started/configuration) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include: package:lints/recommended.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import 'dart:async'; | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
import 'package:http/http.dart' as http; | ||
import 'utils.dart'; | ||
|
||
Future<dynamic> main(final context) async { | ||
throwIfMissing(Platform.environment, ['PANGEA_REDACT_TOKEN']); | ||
|
||
if (context.req.method == 'GET') { | ||
return context.res.send(getStaticFile('index.html'), 200, | ||
{'Content-Type': 'text/html; charset=utf-8'}); | ||
} | ||
|
||
try { | ||
throwIfMissing(context.req.body, ['text']); | ||
} catch (err) { | ||
return context.res.json({'ok': false, 'error': err.toString()}); | ||
} | ||
|
||
final response = | ||
await http.post(Uri.parse('https://redact.aws.eu.pangea.cloud/v1/redact'), | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'Authorization': | ||
'Bearer ${Platform.environment['PANGEA_REDACT_TOKEN']}', | ||
}, | ||
body: jsonEncode({ | ||
'text': context.req.body['text'], | ||
})); | ||
|
||
final data = jsonDecode(response.body); | ||
|
||
return context.res | ||
.json({'ok': true, 'redacted': data['result']['redacted_text']}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import 'dart:io'; | ||
|
||
final String _dirname = Platform.script.toFilePath(); | ||
final String staticFolder = '${Uri.file(_dirname).resolve('../static')}'; | ||
|
||
/// Throws an error if any of the keys are missing from the object | ||
void throwIfMissing(Map<String, dynamic> obj, List<String> keys) { | ||
final missing = <String>[]; | ||
for (var key in keys) { | ||
if (!obj.containsKey(key) || obj[key] == null) { | ||
missing.add(key); | ||
} | ||
} | ||
if (missing.isNotEmpty) { | ||
throw Exception('Missing required fields: ${missing.join(', ')}'); | ||
} | ||
} | ||
|
||
/// Returns the contents of a file in the static folder | ||
/// @param fileName - The name of the file to read | ||
/// @returns Contents of static/{fileName} | ||
String getStaticFile(String fileName) { | ||
return File('$staticFolder/$fileName').readAsStringSync(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
name: censor_with_redact | ||
version: 1.0.0 | ||
|
||
environment: | ||
sdk: ^2.17.0 | ||
|
||
|
||
dev_dependencies: | ||
lints: ^2.0.0 | ||
dependencies: | ||
http: ^1.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Censor with Redact API Demo</title> | ||
|
||
<script> | ||
async function onSubmit(text) { | ||
const response = await fetch('/', { | ||
method: 'POST', | ||
body: JSON.stringify({ text }), | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
|
||
const json = await response.json(); | ||
|
||
if (!json.ok || json.error) { | ||
alert(json.error); | ||
} | ||
|
||
return json.redacted; | ||
} | ||
</script> | ||
|
||
<script src="//unpkg.com/alpinejs" defer></script> | ||
|
||
<link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink" /> | ||
<link rel="stylesheet" href="https://unpkg.com/@appwrite.io/pink-icons" /> | ||
</head> | ||
<body> | ||
<main class="main-content"> | ||
<div class="top-cover u-padding-block-end-56"> | ||
<div class="container"> | ||
<div | ||
class="u-flex u-gap-16 u-flex-justify-center u-margin-block-start-16" | ||
> | ||
<h1 class="heading-level-1">Censor with Redact API Demo</h1> | ||
<code class="u-un-break-text"></code> | ||
</div> | ||
<p | ||
class="body-text-1 u-normal u-margin-block-start-8" | ||
style="max-width: 50rem" | ||
> | ||
Use this page to test your implementation with Redact API. Enter | ||
text and receive the censored message as a response. | ||
</p> | ||
</div> | ||
</div> | ||
<div | ||
class="container u-margin-block-start-negative-56" | ||
x-data="{ message: '', censoredMessage: '', loading: false }" | ||
> | ||
<div class="card u-flex u-gap-24 u-flex-vertical"> | ||
<div class="u-flex u-cross-center u-gap-8"> | ||
<div | ||
class="input-text-wrapper is-with-end-button u-width-full-line" | ||
> | ||
<input x-model="message" type="search" placeholder="Message" /> | ||
<div class="icon-search" aria-hidden="true"></div> | ||
</div> | ||
|
||
<button | ||
class="button" | ||
x-bind:disabled="loading" | ||
x-on:click="async () => { loading = true; censoredMessage = ''; try { censoredMessage = await onSubmit(message) } catch(err) { console.error(err); } finally { loading = false; } }" | ||
> | ||
<span class="text">Censor</span> | ||
</button> | ||
</div> | ||
<template x-if="censoredMessage"> | ||
<div class="u-flex u-flex-vertical u-gap-12"> | ||
<div class="u-flex u-flex-vertical u-gap-12 card"> | ||
<div class="u-flex u-gap-12"> | ||
<h5 class="eyebrow-heading-2">Redact API:</h5> | ||
</div> | ||
|
||
<div style="overflow-x: hidden; line-break: anywhere"> | ||
<p class="u-color-text-gray" x-text="censoredMessage"></p> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
</div> | ||
</div> | ||
</main> | ||
</body> | ||
</html> |
Oops, something went wrong.