Skip to content

Commit

Permalink
Merge branch 'release/0.4.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
lucapette committed Dec 29, 2020
2 parents b70a369 + c837fd7 commit adc9953
Show file tree
Hide file tree
Showing 326 changed files with 6,164 additions and 2,529 deletions.
45 changes: 45 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/recommended"],
"plugins": ["react", "@typescript-eslint"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
}
},

"env": {
"browser": true,
"es2021": true,
"node": true
},

"rules": {
"react/prop-types": 0,
"@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "_"}],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-interface": 0,
"@typescript-eslint/ban-types": ["error", {"extendDefaults": true, "types": {"{}": false, "Object": false}}]
},
"settings": {
"react": {
"version": "16.12"
}
},
"overrides": [
{
"files": ["frontend/chat-plugin/**/*.tsx"],
"settings": {
"react": {
"pragma": "h"
},
"import/resolver": {
"node": {
"extensions": [".ts", ".tsx"]
}
}
}
}
]
}
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.3.0
0.4.0
7 changes: 3 additions & 4 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,9 @@ load(

container_pull(
name = "java_base",
digest = "sha256:9f080b14f9d2c42b7a753169daf5ee7f6c0cbaa36d51ab4390a132941df0b111",
registry = "index.docker.io",
repository = "library/openjdk",
tag = "11.0.3-jre-slim",
registry = "gcr.io",
repository = "distroless/java",
tag = "11",
)

container_pull(
Expand Down
24 changes: 0 additions & 24 deletions backend/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,6 @@ java_library(
],
)

java_library(
name = "channel",
exports = [
"//backend/avro/communication:channel",
"//lib/java/kafka/schema:application-communication-channels",
],
)

java_library(
name = "message",
exports = [
"//backend/avro/communication:message",
"//lib/java/kafka/schema:application-communication-messages",
],
)

java_library(
name = "metadata",
exports = [
"//backend/avro/communication:metadata-action",
"//lib/java/kafka/schema:application-communication-metadata",
],
)

java_library(
name = "read-receipt",
exports = [
Expand Down
3 changes: 1 addition & 2 deletions backend/api/admin/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ load("//tools/build:container_push.bzl", "container_push")
app_deps = [
"//backend:base_app",
"//:springboot_actuator",
"//backend:channel",
"//backend/model/channel:channel",
"//backend:tag",
"//backend:webhook",
"//lib/java/payload",
"//lib/java/uuid",
"//lib/java/spring/auth:spring-auth",
"//lib/java/spring/web:spring-web",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,153 +2,78 @@

import co.airy.avro.communication.Channel;
import co.airy.avro.communication.ChannelConnectionState;
import co.airy.core.api.admin.dto.ChannelMetadata;
import co.airy.core.api.admin.payload.AvailableChannelPayload;
import co.airy.core.api.admin.payload.AvailableChannelsRequestPayload;
import co.airy.core.api.admin.payload.AvailableChannelsResponsePayload;
import co.airy.core.api.admin.payload.ChannelsResponsePayload;
import co.airy.core.api.admin.payload.ConnectChannelRequestPayload;
import co.airy.core.api.admin.payload.DisconnectChannelRequestPayload;
import co.airy.payload.response.EmptyResponsePayload;
import co.airy.payload.response.RequestErrorResponsePayload;
import co.airy.kafka.schema.application.ApplicationCommunicationChannels;
import co.airy.model.channel.ChannelPayload;
import co.airy.spring.web.payload.EmptyResponsePayload;
import co.airy.uuid.UUIDv5;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.HashMap;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import static co.airy.model.channel.ChannelPayload.fromChannel;
import static java.util.stream.Collectors.toList;

@RestController
public class ChannelsController {

private final Stores stores;
private final KafkaProducer<String, Channel> producer;
private final String applicationCommunicationChannels = new ApplicationCommunicationChannels().name();

private final Map<String, Source> sourceMap = new HashMap<>();

public ChannelsController(Stores stores, List<Source> sources) {
for (Source source : sources) {
sourceMap.put(source.getIdentifier(), source);
}
public ChannelsController(Stores stores, KafkaProducer<String, Channel> producer) {
this.stores = stores;
this.producer = producer;
}

@PostMapping("/channels.list")
ResponseEntity<ChannelsResponsePayload> connectedChannels() {
final Map<String, Channel> channelsMap = stores.getChannelsMap();

return ResponseEntity.ok(
new ChannelsResponsePayload(
channelsMap.values()
.stream()
.filter((channel -> ChannelConnectionState.CONNECTED.equals(channel.getConnectionState())))
.map(Mapper::fromChannel)
.collect(toList())
)
);
}

@PostMapping("/channels.explore")
ResponseEntity<?> listChannels(@RequestBody @Valid AvailableChannelsRequestPayload requestPayload) {
final String sourceIdentifier = requestPayload.getSource();

final Source source = sourceMap.get(sourceIdentifier);

if (source == null) {
return ResponseEntity.badRequest().body(new RequestErrorResponsePayload(String.format("source %s not implemented", sourceIdentifier)));
}

final List<ChannelMetadata> availableChannels;
ResponseEntity<ChannelsResponsePayload> listChannels() {
final List<Channel> channels = stores.getChannels();

try {
availableChannels = source.getAvailableChannels(requestPayload.getToken());
} catch (SourceApiException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new RequestErrorResponsePayload(e.getMessage()));
}

final Map<String, Channel> channelsMap = stores.getChannelsMap();
final List<String> connectedSourceIds = channelsMap.values()
.stream()
.filter((channel -> ChannelConnectionState.CONNECTED.equals(channel.getConnectionState())))
.map(Channel::getSourceChannelId)
.collect(toList());

return ResponseEntity.ok(
new AvailableChannelsResponsePayload(
availableChannels.stream()
.map((channel) -> AvailableChannelPayload.builder()
.sourceChannelId(channel.getSourceChannelId())
.name(channel.getName())
.imageUrl(channel.getImageUrl())
.connected(connectedSourceIds.contains(channel.getSourceChannelId()))
.build()
)
.collect(toList())
)
);
return ResponseEntity.ok(new ChannelsResponsePayload(channels.stream()
.map(ChannelPayload::fromChannel)
.collect(toList())));
}

@PostMapping("/channels.connect")
ResponseEntity<?> connectChannel(@RequestBody @Valid ConnectChannelRequestPayload requestPayload) {
final String token = requestPayload.getToken();
final String sourceChannelId = requestPayload.getSourceChannelId();
final String sourceIdentifier = requestPayload.getSource();
@PostMapping("/chatplugin.connect")
ResponseEntity<?> connect(@RequestBody @Valid ConnectChannelRequestPayload requestPayload) {
final String sourceChannelId = requestPayload.getName();
final String sourceIdentifier = "chat_plugin";

final String channelId = UUIDv5.fromNamespaceAndName(sourceIdentifier, sourceChannelId).toString();

final Source source = sourceMap.get(sourceIdentifier);

if (source == null) {
return ResponseEntity.badRequest().body(new RequestErrorResponsePayload(String.format("source %s not implemented", source)));
}

final Map<String, Channel> channelsMap = stores.getChannelsMap();
final Channel existingChannel = channelsMap.get(channelId);

if (existingChannel != null && ChannelConnectionState.CONNECTED.equals(existingChannel.getConnectionState())) {
return ResponseEntity.ok(Mapper.fromChannel(existingChannel));
}

final ChannelMetadata channelMetadata;

try {
channelMetadata = source.connectChannel(token, sourceChannelId);
} catch (SourceApiException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new RequestErrorResponsePayload(e.getMessage()));
}

final Channel channel = Channel.newBuilder()
.setId(channelId)
.setConnectionState(ChannelConnectionState.CONNECTED)
.setImageUrl(Optional.ofNullable(requestPayload.getImageUrl()).orElse(channelMetadata.getImageUrl()))
.setName(Optional.ofNullable(requestPayload.getName()).orElse(channelMetadata.getName()))
.setSource(sourceIdentifier)
.setSourceChannelId(sourceChannelId)
.setToken(token)
.setName(requestPayload.getName())
.build();

try {
stores.storeChannel(channel);
producer.send(new ProducerRecord<>(applicationCommunicationChannels, channel.getId(), channel)).get();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
}

return ResponseEntity.ok(Mapper.fromChannel(channel));
return ResponseEntity.ok(fromChannel(channel));
}

@PostMapping("/channels.disconnect")
ResponseEntity<?> disconnectChannel(@RequestBody @Valid DisconnectChannelRequestPayload requestPayload) {
@PostMapping("/chatplugin.disconnect")
ResponseEntity<?> disconnect(@RequestBody @Valid ChannelDisconnectRequestPayload requestPayload) {
final String channelId = requestPayload.getChannelId().toString();

final Map<String, Channel> channelsMap = stores.getChannelsMap();
final Channel channel = channelsMap.get(channelId);
final Channel channel = stores.getConnectedChannelsStore().get(channelId);

if (channel == null) {
return ResponseEntity.notFound().build();
Expand All @@ -158,28 +83,30 @@ ResponseEntity<?> disconnectChannel(@RequestBody @Valid DisconnectChannelRequest
return ResponseEntity.accepted().build();
}

final Source source = sourceMap.get(channel.getSource());

if (source == null) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new RequestErrorResponsePayload(String.format("source %s not implemented", channel.getSource())));
}

try {
source.disconnectChannel(channel.getToken(), channel.getSourceChannelId());
} catch (SourceApiException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new RequestErrorResponsePayload(e.getMessage()));
}

channel.setConnectionState(ChannelConnectionState.DISCONNECTED);
channel.setToken(null);

try {
stores.storeChannel(channel);
producer.send(new ProducerRecord<>(applicationCommunicationChannels, channel.getId(), channel)).get();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build();
}

return ResponseEntity.ok(new EmptyResponsePayload());
}

}

@Data
@NoArgsConstructor
class ConnectChannelRequestPayload {
@NotNull
private String name;
}

@Data
@NoArgsConstructor
class ChannelDisconnectRequestPayload {
@NotNull
private UUID channelId;
}
16 changes: 0 additions & 16 deletions backend/api/admin/src/main/java/co/airy/core/api/admin/Mapper.java

This file was deleted.

15 changes: 0 additions & 15 deletions backend/api/admin/src/main/java/co/airy/core/api/admin/Source.java

This file was deleted.

This file was deleted.

Loading

0 comments on commit adc9953

Please sign in to comment.