Skip to content

Commit 129935f

Browse files
authored
URL encode user-inputted Ids, migrate to Github actions (#63)
* fix: URL encode user-inputted Ids to prevent injection Also allow special characters to be used in Ids * ci: migrate from circleci to github actions * fix: build error `The system cannot find the path specified` for `openapi.yml` file * fix-build: javadoc * fix: use enum for documents index actions query param - breaking change: documents index actions is now an enum instead of string * ci: run tests using jdk 8, 11, 17 * fix-build: javadoc `bad use of '>'` * fix-build: declare `generateSwaggerCodeTypesense` as dependency for task `sourcesJar` `Task ':sourcesJar' uses this output of task ':generateSwaggerCodeTypesense' without declaring an explicit or implicit dependency` * ci: use matrix for artifact name * ci: test results logging * ci: remove unused `books.jsonl` downloading * build: fail fast for task `downloadApiSpec` * remove unnecessary URL encoding of special characters
1 parent 931b97b commit 129935f

File tree

17 files changed

+471
-363
lines changed

17 files changed

+471
-363
lines changed

.circleci/config.yml

Lines changed: 0 additions & 66 deletions
This file was deleted.

.github/workflows/test.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
- '**/*.md'
7+
pull_request:
8+
paths-ignore:
9+
- '**/*.md'
10+
11+
jobs:
12+
test:
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
java: ['8', '11', '17']
17+
services:
18+
typesense:
19+
image: typesense/typesense:27.0
20+
ports:
21+
- 8108:8108/tcp
22+
volumes:
23+
- /tmp/typesense-server-data:/data
24+
env:
25+
TYPESENSE_DATA_DIR: '/data'
26+
TYPESENSE_API_KEY: 'xyz'
27+
TYPESENSE_ENABLE_CORS: true
28+
TYPESENSE_URL: 'http://localhost:8108'
29+
name: Java ${{ matrix.Java }}
30+
steps:
31+
- name: Checkout sources
32+
uses: actions/checkout@v4
33+
34+
- name: Setup Java
35+
uses: actions/setup-java@v4
36+
with:
37+
distribution: 'temurin'
38+
java-version: ${{ matrix.java }}
39+
- name: Setup Gradle
40+
uses: gradle/actions/setup-gradle@v4
41+
42+
- name: Build with Gradle
43+
run: ./gradlew build
44+
45+
- name: Upload build artifacts
46+
uses: actions/upload-artifact@v4
47+
with:
48+
name: Java ${{ matrix.Java }}
49+
path: build/libs

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
.out/
55
**/books.jsonl
66
config.json
7+
/bin

build.gradle

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ plugins {
77
id 'org.hidetake.swagger.generator' version '2.19.2'
88
}
99

10+
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
11+
import org.gradle.api.tasks.testing.logging.TestLogEvent
12+
1013
apply plugin: DownloadSpecsPlugin
1114

1215
repositories {
@@ -29,6 +32,42 @@ jar {
2932
exclude "META-INF/DEPENDENCIES"
3033
}
3134

35+
tasks.withType(Test) {
36+
testLogging {
37+
// set options for log level LIFECYCLE
38+
events TestLogEvent.FAILED,
39+
TestLogEvent.PASSED,
40+
TestLogEvent.SKIPPED,
41+
TestLogEvent.STANDARD_OUT
42+
exceptionFormat TestExceptionFormat.FULL
43+
showExceptions true
44+
showCauses true
45+
showStackTraces true
46+
47+
// set options for log level DEBUG and INFO
48+
debug {
49+
events TestLogEvent.STARTED,
50+
TestLogEvent.FAILED,
51+
TestLogEvent.PASSED,
52+
TestLogEvent.SKIPPED,
53+
TestLogEvent.STANDARD_ERROR,
54+
TestLogEvent.STANDARD_OUT
55+
exceptionFormat TestExceptionFormat.FULL
56+
}
57+
info.events = debug.events
58+
info.exceptionFormat = debug.exceptionFormat
59+
60+
afterSuite { desc, result ->
61+
if (!desc.parent) { // will match the outermost suite
62+
def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
63+
def startItem = '| ', endItem = ' |'
64+
def repeatLength = startItem.length() + output.length() + endItem.length()
65+
println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
66+
}
67+
}
68+
}
69+
}
70+
3271
sourceSets {
3372
integrationTest {
3473
compileClasspath += sourceSets.main.output
@@ -94,6 +133,7 @@ swaggerSources {
94133
}
95134

96135
swaggerSources.typesense.code.dependsOn downloadApiSpec
136+
sourcesJar.dependsOn swaggerSources.typesense.code
97137
compileJava.dependsOn swaggerSources.typesense.code
98138
sourceSets.main.java.srcDir "${swaggerSources.typesense.code.outputDir}/src/main/java"
99139
sourceSets.main.resources.srcDir "${swaggerSources.typesense.code.outputDir}/src/main/resources"

buildSrc/src/main/groovy/DownloadSpecsPlugin.groovy

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ class DownloadSpecsPlugin implements Plugin<Project> {
1212
void apply(Project project) {
1313
project.tasks.register("downloadApiSpec") {
1414
println('Downloading spec')
15-
new File("${project.buildDir}/openapi.yml").withOutputStream { out ->
15+
File file = new File("${project.buildDir}/openapi.yml")
16+
if (!file.getParentFile().exists())
17+
file.getParentFile().mkdirs();
18+
if (!file.exists())
19+
file.createNewFile();
20+
file.withOutputStream { out ->
1621
new URL(specUrl).withInputStream { from -> out << from }
1722
}
1823
}

src/main/java/org/typesense/api/Alias.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.typesense.api;
22

3+
import org.typesense.api.utils.URLEncoding;
34
import org.typesense.model.CollectionAlias;
45

56
public class Alias {
@@ -20,7 +21,7 @@ public CollectionAlias delete() throws Exception {
2021
return this.apiCall.delete(this.getEndpoint(), null, CollectionAlias.class);
2122
}
2223

23-
public String getEndpoint(){
24-
return Aliases.RESOURCE_PATH + "/" + this.name;
24+
public String getEndpoint() {
25+
return Aliases.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(this.name);
2526
}
2627
}

src/main/java/org/typesense/api/Aliases.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.typesense.api;
22

3+
import org.typesense.api.utils.URLEncoding;
34
import org.typesense.model.CollectionAlias;
45
import org.typesense.model.CollectionAliasSchema;
56
import org.typesense.model.CollectionAliasesResponse;
@@ -9,13 +10,13 @@ public class Aliases {
910
private ApiCall apiCall;
1011
public final static String RESOURCE_PATH = "/aliases";
1112

12-
public Aliases(ApiCall apiCall){
13+
public Aliases(ApiCall apiCall) {
1314
this.apiCall = apiCall;
1415
}
1516

16-
1717
public CollectionAlias upsert(String name, CollectionAliasSchema collectionAliasSchema) throws Exception {
18-
return this.apiCall.put(RESOURCE_PATH + "/" + name, collectionAliasSchema, null, CollectionAlias.class);
18+
return this.apiCall.put(RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(name), collectionAliasSchema, null,
19+
CollectionAlias.class);
1920
}
2021

2122
public CollectionAliasesResponse retrieve() throws Exception {

src/main/java/org/typesense/api/Collection.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.typesense.api;
22

3+
import org.typesense.api.utils.URLEncoding;
34
import org.typesense.model.CollectionResponse;
45
import org.typesense.model.CollectionUpdateSchema;
56

@@ -25,11 +26,11 @@ public class Collection {
2526

2627
private final String endpoint;
2728

28-
Collection(String name, ApiCall apiCall, Configuration configuration){
29-
this.name =name;
29+
Collection(String name, ApiCall apiCall, Configuration configuration) {
30+
this.name = name;
3031
this.apiCall = apiCall;
3132
this.configuration = configuration;
32-
this.endpoint = Collections.RESOURCE_PATH + "/" + this.name;
33+
this.endpoint = Collections.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(this.name);
3334
this.documents = new Documents(this.name, this.apiCall, this.configuration);
3435
this.individualDocuments = new HashMap<>();
3536
this.synonyms = new Synonyms(this.name, this.apiCall);
@@ -50,44 +51,44 @@ public CollectionResponse delete() throws Exception {
5051
return this.apiCall.delete(endpoint, null, CollectionResponse.class);
5152
}
5253

53-
public Documents documents(){
54+
public Documents documents() {
5455
return this.documents;
5556
}
5657

57-
public Document documents(String documentId){
58+
public Document documents(String documentId) {
5859
Document retVal;
5960

60-
if(!this.individualDocuments.containsKey(documentId)){
61-
this.individualDocuments.put(documentId,new Document(this.name, documentId, this.apiCall));
61+
if (!this.individualDocuments.containsKey(documentId)) {
62+
this.individualDocuments.put(documentId, new Document(this.name, documentId, this.apiCall));
6263
}
6364

6465
retVal = this.individualDocuments.get(documentId);
65-
return retVal;
66+
return retVal;
6667
}
6768

68-
public Synonyms synonyms(){
69+
public Synonyms synonyms() {
6970
return this.synonyms;
7071
}
7172

72-
public Synonym synonyms(String synonymId){
73+
public Synonym synonyms(String synonymId) {
7374
Synonym retVal;
7475

75-
if(!this.individualSynonyms.containsKey(synonymId)){
76+
if (!this.individualSynonyms.containsKey(synonymId)) {
7677
this.individualSynonyms.put(synonymId, new Synonym(this.name, synonymId, this.apiCall));
7778
}
7879

7980
retVal = this.individualSynonyms.get(synonymId);
80-
return retVal;
81+
return retVal;
8182
}
8283

83-
public Overrides overrides(){
84+
public Overrides overrides() {
8485
return this.overrides;
8586
}
8687

87-
public Override overrides(String overrideId){
88+
public Override overrides(String overrideId) {
8889
Override retVal;
8990

90-
if(!this.individualOverrides.containsKey(overrideId)){
91+
if (!this.individualOverrides.containsKey(overrideId)) {
9192
this.individualOverrides.put(overrideId, new Override(this.name, overrideId, this.apiCall));
9293
}
9394

src/main/java/org/typesense/api/Document.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.typesense.api;
22

33
import java.util.Map;
4+
import org.typesense.api.utils.URLEncoding;
45

56
public class Document {
67
private String collectionName;
@@ -13,18 +14,19 @@ public class Document {
1314
this.documentId = documentId;
1415
this.apiCall = apiCall;
1516

16-
this.endpoint = Collections.RESOURCE_PATH + "/" + this.collectionName + Documents.RESOURCE_PATH + "/" + this.documentId;
17+
this.endpoint = Collections.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(this.collectionName)
18+
+ Documents.RESOURCE_PATH + "/" + URLEncoding.encodeURIComponent(this.documentId);
1719
}
1820

19-
public Map<String,Object> retrieve() throws Exception {
21+
public Map<String, Object> retrieve() throws Exception {
2022
return this.apiCall.get(endpoint, null, Map.class);
2123
}
2224

2325
public Map<String, Object> delete() throws Exception {
2426
return this.apiCall.delete(this.endpoint, null, Map.class);
2527
}
2628

27-
public Map<String , Object> update(Map<String, Object> document) throws Exception {
29+
public Map<String, Object> update(Map<String, Object> document) throws Exception {
2830
return this.apiCall.patch(this.endpoint, document, null, Map.class);
2931
}
3032

0 commit comments

Comments
 (0)