4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.security;
17 |
18 | public class AuthenticationProviderUserPassword {//*implements AuthenticationProvider {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/wonky/model/TelegramInfo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.model;
17 |
18 | public class TelegramInfo {
19 | private boolean activated;
20 | private boolean showChannels;
21 | private String name;
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/wonky/api/Invite.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.api;
17 |
18 | import io.micronaut.core.annotation.Introspected;
19 | import lombok.Getter;
20 | import lombok.Setter;
21 |
22 | @Getter
23 | @Setter
24 | @Introspected
25 | public class Invite {
26 | private String email;
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/wonky/Application.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky;
17 |
18 | import io.micronaut.runtime.Micronaut;
19 |
20 | /**
21 | * Created by domix on 01/06/18.
22 | */
23 | public class Application {
24 |
25 | public static void main(String[] args) {
26 | Micronaut.run(Application.class);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/src/main/java/wonky/model/Organization.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.model;
17 |
18 | import io.micronaut.core.annotation.Introspected;
19 | import lombok.Getter;
20 | import lombok.Setter;
21 | import wonky.slack.Team;
22 |
23 | @Setter
24 | @Getter
25 | @Introspected
26 | public class Organization {
27 | private Team team;
28 | //TODO: Users info
29 | //TODO: channels info
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/wonky/service/SlackOrganization.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.service;
17 |
18 | import io.micronaut.core.annotation.Introspected;
19 | import lombok.Getter;
20 | import lombok.Setter;
21 |
22 | /**
23 | * Created by domix on 01/06/18.
24 | */
25 | @Setter
26 | @Getter
27 | @Introspected
28 | public class SlackOrganization {
29 | private String token;
30 | private String wonkyDomain;
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/wonky/slack/Team.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.slack;
17 |
18 | import com.fasterxml.jackson.annotation.JsonProperty;
19 | import io.micronaut.core.annotation.Introspected;
20 | import lombok.Getter;
21 | import lombok.Setter;
22 |
23 | /**
24 | * Created by domix on 05/06/18.
25 | */
26 | @Setter
27 | @Getter
28 | @Introspected
29 | public class Team {
30 | private String domain;
31 | @JsonProperty("email_domain")
32 | private String emailDomain;
33 | private Icon icon;
34 | private String id;
35 | private String name;
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/wonky/service/EntityNotFoundException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.service;
17 |
18 | import io.micronaut.core.annotation.Introspected;
19 | import lombok.Getter;
20 |
21 | @Getter
22 | @Introspected
23 | public class EntityNotFoundException extends RuntimeException {
24 | private final String entity;
25 | private final String id;
26 |
27 | public EntityNotFoundException(String entity, String id) {
28 | this("The entity can not be found.", entity, id);
29 | }
30 |
31 | public EntityNotFoundException(String message, String entity, String id) {
32 | super(message);
33 |
34 | this.entity = entity;
35 | this.id = id;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/wonky/http/SlackResponseException.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.http;
17 |
18 | import io.micronaut.core.annotation.Introspected;
19 | import lombok.Getter;
20 |
21 | @Getter
22 | @Introspected
23 | public class SlackResponseException extends RuntimeException {
24 | private final String error;
25 | private final String slackResponse;
26 |
27 | public SlackResponseException(String error, String slackResponse) {
28 | this("Slack error response", error, slackResponse);
29 | }
30 |
31 | public SlackResponseException(String message, String error, String slackResponse) {
32 | super(message);
33 | this.error = error;
34 | this.slackResponse = slackResponse;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/wonky/config/Bootstrap.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.config;
17 |
18 | import io.micronaut.context.event.StartupEvent;
19 | import io.micronaut.runtime.event.annotation.EventListener;
20 | import io.micronaut.scheduling.annotation.Async;
21 | import jakarta.inject.Singleton;
22 | import lombok.extern.slf4j.Slf4j;
23 | import wonky.service.SlackService;
24 |
25 | @Slf4j
26 | @Singleton
27 | public class Bootstrap {
28 | private final SlackService slackService;
29 |
30 | public Bootstrap(SlackService slackService) {
31 | this.slackService = slackService;
32 | }
33 |
34 | @EventListener
35 | @Async
36 | void onStartup(StartupEvent event) {
37 | slackService.loadAllOrgs();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/wonky/slack/Icon.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.slack;
17 |
18 | import com.fasterxml.jackson.annotation.JsonProperty;
19 | import io.micronaut.core.annotation.Introspected;
20 | import lombok.Getter;
21 | import lombok.Setter;
22 |
23 | /**
24 | * Created by domix on 05/06/18.
25 | */
26 | @Setter
27 | @Getter
28 | @Introspected
29 | public class Icon {
30 | @JsonProperty("image_102")
31 | private String image102;
32 | @JsonProperty("image_132")
33 | private String image132;
34 | @JsonProperty("image_230")
35 | private String image230;
36 | @JsonProperty("image_34")
37 | private String image34;
38 | @JsonProperty("image_44")
39 | private String image44;
40 | @JsonProperty("image_68")
41 | private String image68;
42 | @JsonProperty("image_88")
43 | private String image88;
44 | @JsonProperty("image_original")
45 | private String imageOriginal;
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/groovy/wonky/json/JacksonUtilSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (C) 2014-2019 the original author or authors.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package wonky.json
18 |
19 | import com.fasterxml.jackson.databind.ObjectMapper
20 | import spock.lang.Specification
21 | import wonky.slack.Team
22 |
23 | class JacksonUtilSpec extends Specification {
24 | def foo() {
25 | given:
26 | def util = new JacksonUtil(new ObjectMapper())
27 | Team team = new Team(domain: 'dd.com')
28 | def json = util.toJson(team)
29 | expect:
30 | util.readValue(json, null, Team)
31 | }
32 |
33 | def bar() {
34 | when:
35 | def util = new JacksonUtil(new ObjectMapper())
36 | util.readValue("ssffs", null, Team)
37 | then:
38 | thrown RuntimeException
39 | when:
40 | util.readValue("ssffs", "ss", Team)
41 | then:
42 | thrown RuntimeException
43 | when:
44 | util.toJson(new Object())
45 | then:
46 | thrown RuntimeException
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/wonky/http/SlackResponseExceptionHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.http;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.http.HttpRequest;
20 | import io.micronaut.http.HttpResponse;
21 | import io.micronaut.http.annotation.Produces;
22 | import io.micronaut.http.server.exceptions.ExceptionHandler;
23 | import jakarta.inject.Singleton;
24 |
25 | import static io.micronaut.core.util.CollectionUtils.mapOf;
26 |
27 | @Produces
28 | @Singleton
29 | @Requires(classes = {SlackResponseException.class, ExceptionHandler.class})
30 | public class SlackResponseExceptionHandler implements ExceptionHandler> {
31 |
32 | @Override
33 | public HttpResponse> handle(HttpRequest request, SlackResponseException exception) {
34 | final var data = mapOf(
35 | "message", exception.getMessage(),
36 | "error", exception.getError(),
37 | "slackResponse", exception.getSlackResponse());
38 |
39 | return HttpResponse.serverError(data);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/wonky/http/EntityNotFoundExceptionHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.http;
17 |
18 | import io.micronaut.context.annotation.Requires;
19 | import io.micronaut.http.HttpRequest;
20 | import io.micronaut.http.HttpResponse;
21 | import io.micronaut.http.annotation.Produces;
22 | import io.micronaut.http.server.exceptions.ExceptionHandler;
23 | import jakarta.inject.Singleton;
24 | import wonky.service.EntityNotFoundException;
25 |
26 | import static io.micronaut.core.util.CollectionUtils.mapOf;
27 |
28 | @Produces
29 | @Singleton
30 | @Requires(classes = {EntityNotFoundException.class, ExceptionHandler.class})
31 | public class EntityNotFoundExceptionHandler implements ExceptionHandler> {
32 |
33 | @Override
34 | public HttpResponse> handle(HttpRequest request, EntityNotFoundException exception) {
35 | final var data = mapOf(
36 | "message", exception.getMessage(),
37 | "entity", exception.getEntity(),
38 | "id", exception.getId());
39 | return HttpResponse.notFound(data);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/groovy/wonky/service/SlackServiceSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (C) 2014-2019 the original author or authors.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package wonky.service
18 |
19 | import com.fasterxml.jackson.databind.ObjectMapper
20 | import spock.lang.Ignore
21 | import spock.lang.Specification
22 | import wonky.http.SlackClient
23 | import wonky.json.JacksonUtil
24 | import wonky.model.TelegramInfo
25 | import wonky.security.AuthenticationProviderUserPassword
26 |
27 | /**
28 | * Created by domix on 01/06/18.
29 | */
30 | class SlackServiceSpec extends Specification {
31 |
32 | def smoke() {
33 | given:
34 | new TelegramInfo()
35 | new AuthenticationProviderUserPassword()
36 | expect:
37 | //WTF!
38 | true
39 | }
40 |
41 | def foo() {
42 | given:
43 | def service = new SlackService(Mock(SlackClient), './src/test/resources/foo.yaml', 100)
44 | service.load()
45 | expect:
46 | service.orgs.size() == 2
47 | }
48 |
49 | @Ignore
50 | def foo2() {
51 | given:
52 | def token = System.getenv("TOKEN")
53 | assert token
54 | def jacksonUtil = new JacksonUtil(objectMapper: new ObjectMapper())
55 | def service = new SlackService(tenantsFile: './src/test/resources/foo.yaml', jacksonUtil: jacksonUtil)
56 | def information = service.tenantSlackInformation(token)
57 | expect:
58 | information
59 | information.icon.imageOriginal
60 | println information.getIcon().getImageOriginal()
61 | }
62 |
63 | def bar() {
64 | when:
65 | def service = new SlackService(Mock(SlackClient), './src/test/resources/notfile.yaml', 100)
66 | service.load()
67 | then:
68 | thrown IllegalStateException
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/wonky/json/JacksonUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.json;
17 |
18 | import com.fasterxml.jackson.core.JsonProcessingException;
19 | import com.fasterxml.jackson.databind.JsonNode;
20 | import com.fasterxml.jackson.databind.ObjectMapper;
21 | import jakarta.inject.Singleton;
22 |
23 | import java.io.IOException;
24 |
25 | import static io.micronaut.core.util.StringUtils.isNotEmpty;
26 |
27 | /**
28 | * Created by domix on 05/06/18.
29 | */
30 | @Singleton
31 | public class JacksonUtil {
32 | private final ObjectMapper objectMapper;
33 |
34 | public JacksonUtil(ObjectMapper objectMapper) {
35 | this.objectMapper = objectMapper;
36 | }
37 |
38 | public String toJson(Object d) {
39 | try {
40 | return objectMapper.writeValueAsString(d);
41 | } catch (JsonProcessingException e) {
42 | //TODO: improve exception handling
43 | throw new RuntimeException(e.getMessage(), e);
44 | }
45 | }
46 |
47 | public T readValue(String content, String node, Class valueType) {
48 | if (isNotEmpty(node)) {
49 | try {
50 | JsonNode jsonNode = objectMapper.readTree(content).get(node);
51 | return objectMapper.treeToValue(jsonNode, valueType);
52 | } catch (IOException e) {
53 | //TODO: improve exception handling
54 | throw new RuntimeException(e.getMessage(), e);
55 | }
56 | } else {
57 | return readValue(content, valueType);
58 | }
59 | }
60 |
61 | public T readValue(String content, Class valueType) {
62 | try {
63 | return objectMapper.readValue(content, valueType);
64 | } catch (IOException e) {
65 | //TODO: improve exception handling
66 | throw new RuntimeException(e.getMessage(), e);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk: openjdk17
4 |
5 | env:
6 | global:
7 | - WONKY_TENANTS_FILE=./orgs_ignored.yaml
8 | - secure: YynxQ8ZEPhnPo3bgAJqZ4l0gvUqHLV+D7eMS0/bmxR3PkCjVjZmW80UKJnj2a4fXOX6AI1snWp8WfbGjgV7gmoNYeFdk47Ym4UQR8yXPaAq1sf4IZXJmQ4j1cFLGDQgsdTsUbZwcIJYwPt7BN0ecOWtscr9P1ohxlGsVnKw0k51qqRi0YmpRf6SWEqwkAw/lz32ukHQH4phguUBtw9+YV2C5y+fqSMByidLFeengInwncCos5cFUPOSqDzjxbG1Q+fUN9UQrGbCs9DZV5cTQoDxo9NA6cNJo6cTmVKx1kh2vC8aQSw6TuYiZJIltH84LchL5qQ81A1/fVR/CXy+UWH2uxbWVwtQ8ttH+eu9aCCOnPjewRAu0blimgixTZHl2mfHGoN3vybFT8krwZEPeqgYile095BVai9P/0R0P2aAvsHz1tc5e3IC0axPjav8eETZv89ohELfLdbWO289FsVvTxTCkpagBHE35651RAXyP2dhctKLnqfhsfvaerwTChgf2q7Xddlp9pfmZwNeAQ/19xp+cEwdlZEq4H+LU3oecsWY5J2ie0qdpbXnoL9z2xaNP/ZScdSHadlauc1Qo8xZnPy/kFQ6vdrqW0DlxmK5SZoGpBJCuMdMUMog3VX6/W0tgNkypS+FhD8sp1MfUDnU3mInSbfp3x4rJA5ftq44=
9 | - secure: HRwJQXRVUkGz90S7TF7TUsk1vVDMpecgmnF8V/DlBRQIgxuMrFMXk5HvlfPhy9BrJb83oviIVXtttC/Kkf2FWxPOa8ifHQDiLZC1Le74Cfl4lGiWCSj2E0NVxh64UiZjWNFy8JI+ZVH1NO34UNc67xbbcryKdIKffLlFzJKdfAbFnfOowsykJoRMPXGccyO6NipFXDy+pOsjjq61XvrsiQqW1Kfv5WcCPwIIKP0A0R0eFb1/7T6K2Fe+eeBotq3nxTMtNqzUeQzxyeeCusiO0OTzy+sS2eimFRUOdFXc39PQjqETM0ly5kj9IMzJuNuKJZq6IDOcUCInBduQXQhmkBeiThED5OSzdvbtWnPKxfTZ7069oG8M8LOUmmIODRdQWl9rvtJrKP0JodiVNzrJXeb2SG3bP5kANy7s9nEqmK3IzZtHDisFUcIqkDzL1e9lDYAbEyE/sVczDidD+gajyGPDHMC/K7aXABA15l0iCYStE0J6rZA14ztM9dNKIHjAhcFrS/sr/j6ol/pRWZahlq4uYKElDu3LhFRVMby4jaPjide1JUzZWsC8JjS6r8bcSXdiEL9ykcTbPYCCzz0g580YjpDy7R9H6/OLRYbAFlbwwiQvalZQ/nD5LLx7FTkzeCC209VVA839vXYm/xVyK/3vpxGxwQ/fy75SlYUH1CU=
10 | - secure: VfRcsDTQyazo/zd1dzPiTjwU+NwfAMrFsemZXi8igi68ZdDOVlWYwhReJ6bX6rH1S5uFNe9ozgpU7j5+OzIRfFd94CvvFm1vGuXaIwam3BIR4coDx9f0H2+bct7zVR0bdWgtbPpSkAa3WEv1ASh1K2kYysgytEthExrXCjwwU4o/Dz5UFNEoIbPkCNf9yzyoGjr6uJHkOuf2HrIj3KUPUog/M9Cxd8h2xOBrIX4XicW7fJ4BMlfJRh9Y7pzttbJMQ4ER7hX4lCNaENduMLUmupgnNKAkkLW8HNR1ee0HbXK5olzG+YZza/NS+1XkDB/cpSaIHcdUu/3Gyn7v2Ve2X3q8rcLOoiBMQaCYWf/kA1EIEzyyh3ACCI3VwJCpFPZ2E+dmckYncG3g13Xs/Ff8rE1yaMMwes+muUdS58IrEj000nhMARc4/jnG93+4V7a/MHBNi0NhJhZJP5cF04ZkenF18yZAQFMZbQwLQG1ScVX5bw3mgmQzwDkLjWA4W5BBck704l1eyTAfkrYWbkqo7pgu1a+UumZnUMkka1nBgdPUxNT+ZZErlzbWwXOg9QUdEJGJAA3pLGOPCRZfE2pI6TBhC2Ls6we2Z9sKwrnW9uUN51r8Ahcc9I1696LLTrKZiUBWxaPthWfSUh06Il+EGvRl+W2JweiXRjETwbCAlm4=
11 |
12 | before_cache:
13 | - rm -fr $HOME/.gradle/caches/modules-2/modules-2.lock
14 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
15 |
16 | cache:
17 | directories:
18 | - $HOME/.gradle/caches/
19 | - $HOME/.gradle/wrapper/
20 |
21 | before_install:
22 | - openssl aes-256-cbc -K $encrypted_55795232bcfe_key -iv $encrypted_55795232bcfe_iv
23 | -in orgs_ignored.yaml.enc -out orgs_ignored.yaml -d
24 |
25 | install: skip
26 |
27 | script:
28 | - "./gradlew build --warning-mode=all"
29 |
--------------------------------------------------------------------------------
/src/main/java/wonky/api/ApiController.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.api;
17 |
18 | import io.micronaut.http.HttpResponse;
19 | import io.micronaut.http.HttpResponseFactory;
20 | import io.micronaut.http.annotation.Body;
21 | import io.micronaut.http.annotation.Controller;
22 | import io.micronaut.http.annotation.Get;
23 | import io.micronaut.http.annotation.Header;
24 | import io.micronaut.http.annotation.Post;
25 | import io.micronaut.http.annotation.QueryValue;
26 | import io.micronaut.security.annotation.Secured;
27 | import io.micronaut.security.rules.SecurityRule;
28 | import lombok.extern.slf4j.Slf4j;
29 | import wonky.model.Organization;
30 | import wonky.service.SlackService;
31 |
32 | import java.util.Optional;
33 |
34 | import static io.micronaut.http.HttpHeaders.ACCEPT_LANGUAGE;
35 | import static io.micronaut.http.HttpHeaders.HOST;
36 |
37 | /**
38 | * Created by domix on 01/06/18.
39 | */
40 | @Slf4j
41 | @Controller("/v1")
42 | @Secured(SecurityRule.IS_ANONYMOUS)
43 | public class ApiController {
44 | private SlackService slackService;
45 |
46 | public ApiController(SlackService slackService) {
47 | this.slackService = slackService;
48 | }
49 |
50 | @Get("/organizations/_self")
51 | public HttpResponse index(@Header(HOST) String hostname, @Header(value = ACCEPT_LANGUAGE, defaultValue = "en") String language) {
52 | String locale = locale(language);
53 |
54 | return HttpResponseFactory.INSTANCE.ok(getOrganizationByDomain(hostname));
55 | }
56 |
57 | private String locale(@Header(value = ACCEPT_LANGUAGE, defaultValue = "en") String language) {
58 | return Optional.ofNullable(language).orElse("en");
59 | }
60 |
61 | @Get("/organizations/{hostname}")
62 | public Organization forDomain(@QueryValue("hostname") String hostname, @Header(value = ACCEPT_LANGUAGE, defaultValue = "en") String language) {
63 | return getOrganizationByDomain(hostname);
64 | }
65 |
66 | @Post("/invites")
67 | public String invite(@Header(HOST) String hostname, @Body Invite invite, @Header(value = ACCEPT_LANGUAGE, defaultValue = "en") String language) {
68 | return slackService.invite(hostname, invite);
69 | }
70 |
71 | private Organization getOrganizationByDomain(String hostname) {
72 | log.info("Looking for [{}]", hostname);
73 |
74 | return slackService.get(hostname);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/src/main/java/wonky/http/SlackClient.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package wonky.http;
17 |
18 | import io.micronaut.http.HttpRequest;
19 | import io.micronaut.http.client.HttpClient;
20 | import io.micronaut.http.client.annotation.Client;
21 | import jakarta.inject.Singleton;
22 | import wonky.json.JacksonUtil;
23 | import wonky.service.SlackOrganization;
24 | import wonky.slack.Team;
25 |
26 | import java.io.UnsupportedEncodingException;
27 | import java.net.URLEncoder;
28 | import java.util.Map;
29 |
30 | import static io.micronaut.http.HttpHeaders.CONTENT_TYPE;
31 | import static io.micronaut.http.HttpRequest.GET;
32 | import static io.micronaut.http.HttpRequest.POST;
33 | import static io.micronaut.http.MediaType.APPLICATION_FORM_URLENCODED;
34 | import static java.lang.String.format;
35 |
36 | @Singleton
37 | public class SlackClient {
38 |
39 | private final HttpClient httpClient;
40 | private final JacksonUtil jacksonUtil;
41 |
42 | public SlackClient(@Client("https://slack.com") HttpClient httpClient, JacksonUtil jacksonUtil) {
43 | this.httpClient = httpClient;
44 | this.jacksonUtil = jacksonUtil;
45 | }
46 |
47 | public Team fetchTeamInfo(String token) {
48 | String uri = format("/api/team.info?token=%s", token);
49 | HttpRequest> req = GET(uri);
50 |
51 | String retrieve = httpClient.toBlocking().retrieve(req);
52 |
53 | return getTeamFromSlackResponse(retrieve);
54 | }
55 |
56 | public String invite(SlackOrganization tenant, String email) {
57 |
58 | String uri = format("/api/users.admin.invite?token=%s", tenant.getToken());
59 | String encodedEmail;
60 |
61 | try {
62 | encodedEmail = URLEncoder.encode(email, "UTF-8");
63 | } catch (UnsupportedEncodingException e) {
64 | throw new RuntimeException("chaz");
65 | }
66 |
67 | String payload = String.format("email=%s", encodedEmail);
68 |
69 | HttpRequest> req = POST(uri, payload)
70 | .header(CONTENT_TYPE, APPLICATION_FORM_URLENCODED);
71 |
72 | return httpClient.toBlocking().exchange(req, String.class).body();
73 | }
74 |
75 | private Team getTeamFromSlackResponse(String response) {
76 | validateSlackError(response);
77 | return jacksonUtil.readValue(response, "team", Team.class);
78 | }
79 |
80 | private void validateSlackError(String body) {
81 | final var map = jacksonUtil.readValue(body, Map.class);
82 | Object ok = map.get("ok");
83 |
84 | boolean result = Boolean.parseBoolean(ok.toString());
85 | if (!result) {
86 | String error = map.getOrDefault("error", "Unknown").toString();
87 | throw new SlackResponseException(error, body);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wonky
2 | [](https://travis-ci.org/domix/wonky)
3 | [](http://codecov.io/github/domix/wonky?branch=master)
4 |
5 |
6 | Wonky is a port of [slacking](https://github.com/rauchg/slackin/), to the JVM written in `Java` and [Micronaut](http://micronaut.io/).
7 |
8 | ## Features
9 |
10 | - A landing page you can point users to fill in their emails and receive an invite (`http://slack.yourdomain.com`)
11 |
12 | ## Build
13 |
14 | Docker Engine
15 |
16 | ### Requirements
17 |
18 | [](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
19 |
20 | ### Slack token
21 |
22 | To build & run wonky you need a `Slack API token`. Note that the user you use to generate the token must be an admin. You may want to create a dedicated @wonky-inviter user (or similar) for this.
23 |
24 | You can find your API token [here](http://api.slack.com/web)
25 |
26 | Once you have the token, you need to write the `configuration file`.
27 |
28 | #### Configuration file
29 |
30 | The configuration file is very simple to write, it's a `YAML`.
31 |
32 | ##### Single Slack organization
33 |
34 | ```YAML
35 | - !!wonky.service.SlackOrganization
36 | token: "xoxp-..."
37 | wonkyDomain: "localhost:8080"
38 | ```
39 |
40 | *NOTE:* Wonky supports multiple organizations (aka multitenancy), Wonky will use the domain (HOST http header) to select the right token. Consider this.
41 |
42 | ##### Multiple Slack organizations
43 |
44 | ```YAML
45 | - !!wonky.service.SlackOrganization
46 | token: "xoxp-..."
47 | wonkyDomain: "localhost:8080"
48 | - !!wonky.service.SlackOrganization
49 | token: "xoxp-..."
50 | wonkyDomain: "slack.myorganization.com"
51 | ```
52 |
53 | ##### Recomendation
54 |
55 | We strongly recommend you write and name the config file as `orgs_ignored.yaml` and save it to the root source of wonky, in git is marked as ignored.
56 |
57 | #### Environment variables
58 |
59 | In order to run properly the test, you have to provide the following `Environment Variables`;
60 |
61 | * WONKY_TENANTS_FILE
62 | * WONKY_TEST_EMAIL_PREFIX
63 |
64 | You can configued as follows in the shell:
65 |
66 | ````bash
67 | $ export WONKY_TENANTS_FILE=./orgs_ignored.yaml
68 | $ export WONKY_TEST_EMAIL_PREFIX=something
69 |
70 | ````
71 |
72 | Now you can build wonky from source :)
73 |
74 | ## Building from source
75 |
76 | ```bash
77 | $ ./gradlew clean build
78 | ```
79 |
80 | ## Run
81 |
82 | By default wonky runs on port `8080`, as any `Micronaut` application you can chance the port as you wish.
83 |
84 |
85 | ```bash
86 | $ ./gradlew run
87 | ```
88 |
89 | Alternatively, you can run Wonky with Docker as a container:
90 |
91 |
92 | ```bash
93 | $ docker run --rm -p 8080:8080 -v `pwd`/orgs_ignored.yaml:/etc/wonky/tenants.yaml domix/wonky:0.3.7
94 | ```
95 |
96 | ### Communities using Wonky
97 |
98 | - [The Data Pub](http://slack.thedata.pub)
99 | - [JavaMexico.org](http://slack.javamexico.org)
100 | - [SpringHispano.org](http://slack.springhispano.org)
101 | - [Groovyando.org](http://slack.groovyando.org)
102 | - [JavaHispano.org](http://slack.javahispano.org)
103 |
104 | ### Development badges
105 |
106 | 
107 |
--------------------------------------------------------------------------------
/src/test/groovy/wonky/api/ApiControllerSpec.groovy:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (C) 2014-2019 the original author or authors.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package wonky.api
18 |
19 | import com.fasterxml.jackson.databind.ObjectMapper
20 | import io.micronaut.context.ApplicationContext
21 | import io.micronaut.core.type.Argument
22 | import io.micronaut.http.HttpRequest
23 | import io.micronaut.http.HttpResponse
24 | import io.micronaut.http.client.HttpClient
25 | import io.micronaut.http.client.exceptions.HttpClientResponseException
26 | import io.micronaut.runtime.server.EmbeddedServer
27 | import org.apache.commons.lang3.RandomStringUtils
28 | import spock.lang.AutoCleanup
29 | import spock.lang.Shared
30 | import spock.lang.Specification
31 | import wonky.json.JacksonUtil
32 | import wonky.model.Organization
33 |
34 | import static io.micronaut.http.HttpRequest.GET
35 | import static io.micronaut.http.HttpRequest.POST
36 | import static io.micronaut.http.HttpStatus.*
37 |
38 | class ApiControllerSpec extends Specification {
39 | @Shared
40 | @AutoCleanup
41 | EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
42 |
43 | @Shared
44 | @AutoCleanup
45 | HttpClient client = embeddedServer.applicationContext.createBean(HttpClient, embeddedServer.getURL())
46 |
47 | def "Getting the organization info"() {
48 | when:
49 | HttpRequest request = GET('/v1/organizations/_self').header("Host", "localhost")
50 |
51 | HttpResponse rsp = client.toBlocking().exchange(request, Argument.of(Organization))
52 | client.toBlocking().exchange(request, Argument.of(Organization))
53 |
54 | then: 'the endpoint can be accessed'
55 | rsp.status == OK
56 | rsp.body()
57 |
58 | when:
59 | def body = rsp.body()
60 |
61 | then:
62 | body.team.name
63 | }
64 |
65 | def "Fail when Getting the organization info"() {
66 | when:
67 | HttpRequest notFound = GET('/v1/organizations/notfound')
68 |
69 | client.toBlocking().exchange(notFound, Argument.of(Map))
70 |
71 | then: 'the endpoint can be accessed'
72 | HttpClientResponseException notFoundException = thrown(HttpClientResponseException)
73 | NOT_FOUND == notFoundException.response.status
74 | def body = notFoundException.response.body()
75 | body.id
76 | body.entity
77 | body.message
78 |
79 | when:
80 | HttpRequest badToken = GET('/v1/organizations/badtoken')
81 |
82 | client.toBlocking().exchange(badToken, Argument.of(Map))
83 |
84 | then: 'the endpoint can be accessed'
85 | HttpClientResponseException badTokenException = thrown(HttpClientResponseException)
86 | INTERNAL_SERVER_ERROR == badTokenException.response.status
87 | def body1 = badTokenException.response.body()
88 | body1.error
89 | body1.message
90 | body1.slackResponse
91 | }
92 |
93 | def "invite"() {
94 | when:
95 | def prefix = System.getenv("WONKY_TEST_EMAIL_PREFIX")
96 | assert prefix
97 | def alphanumeric = RandomStringUtils.randomAlphanumeric(10)
98 | Invite invite = new Invite(email: "${ prefix }+${ alphanumeric }@gmail.com")
99 |
100 | JacksonUtil jacksonUtil = new JacksonUtil(new ObjectMapper())
101 | def jsonInvite = jacksonUtil.toJson(invite)
102 |
103 | HttpRequest notFound = POST('/v1/invites', jsonInvite).header("Host", "localhost")
104 |
105 | def exchange = client.toBlocking().exchange(notFound, Argument.of(Map))
106 |
107 | then: 'the endpoint can be accessed'
108 |
109 | OK == exchange.status()
110 |
111 | }
112 |
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | ## 1. Purpose
4 |
5 | A primary goal of Wonky is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
6 |
7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
8 |
9 | We invite all those who participate in Wonky to help us create safe and positive experiences for everyone.
10 |
11 | ## 2. Open Source Citizenship
12 |
13 | A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
14 |
15 | Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
16 |
17 | If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
18 |
19 | ## 3. Expected Behavior
20 |
21 | The following behaviors are expected and requested of all community members:
22 |
23 | * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
24 | * Exercise consideration and respect in your speech and actions.
25 | * Attempt collaboration before conflict.
26 | * Refrain from demeaning, discriminatory, or harassing behavior and speech.
27 | * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
28 | * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
29 |
30 | ## 4. Unacceptable Behavior
31 |
32 | The following behaviors are considered harassment and are unacceptable within our community:
33 |
34 | * Violence, threats of violence or violent language directed against another person.
35 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
36 | * Posting or displaying sexually explicit or violent material.
37 | * Posting or threatening to post other people’s personally identifying information ("doxing").
38 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
39 | * Inappropriate photography or recording.
40 | * Inappropriate physical contact. You should have someone’s consent before touching them.
41 | * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
42 | * Deliberate intimidation, stalking or following (online or in person).
43 | * Advocating for, or encouraging, any of the above behavior.
44 | * Sustained disruption of community events, including talks and presentations.
45 |
46 | ## 5. Consequences of Unacceptable Behavior
47 |
48 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
49 |
50 | Anyone asked to stop unacceptable behavior is expected to comply immediately.
51 |
52 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
53 |
54 | ## 6. Reporting Guidelines
55 |
56 | If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. domingo.suarez@gmail.com.
57 |
58 |
59 |
60 | Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
61 |
62 | ## 7. Addressing Grievances
63 |
64 | If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Domix with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
65 |
66 |
67 |
68 | ## 8. Scope
69 |
70 | We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business.
71 |
72 | This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
73 |
74 | ## 9. Contact info
75 |
76 | domingo.suarez@gmail.com
77 |
78 | ## 10. License and attribution
79 |
80 | This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
81 |
82 | Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
83 |
84 | Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
85 |
--------------------------------------------------------------------------------
/src/main/java/wonky/service/SlackService.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2014-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *