Skip to content

Commit

Permalink
Asset and Profile events (#93)
Browse files Browse the repository at this point in the history
* avatar and wallpaper update events

* profile create and update event

* update readme

* chore: update openapi types

---------

Co-authored-by: Thiies <Thiies@users.noreply.github.com>
  • Loading branch information
Thiies and Thiies authored Nov 19, 2024
1 parent bf4dd49 commit 7aa8af7
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 14 deletions.
12 changes: 11 additions & 1 deletion api/README-Socket-Updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function connect() {
// deserialize the event
// format:
// groupId: string,
// eventType: MATCHES | PLAYERS | SEASONS | GROUPS | RULES | RULE_MOVES
// eventType: MATCHES | PLAYERS | SEASONS | GROUPS | RULES | RULE_MOVES | ASSETS | PROFILES
// scope: string
// body: a dto matching the eventType (MatchDto, PlayerDto, ...)
const socketEvent = JSON.parse(event.data);
Expand Down Expand Up @@ -117,6 +117,16 @@ A list of all event types with their corresponding dto and all available scopes:

* **seasonStart:** When a new season is started

#### Assets (body: AssetMetadataDto | ProfileAssetMetadataDto)

* **groupWallpaperSet:** When a groups wallpaper is updated
* **profileAvatarSet:** When a profiles avatar is updated
*
#### Profiles (body: ProfileDto)

* **profileCreate:** When a profile is created
* **profileUpdate:** When a profile is updated

### TODO

* Secure socket
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
import pro.beerpong.api.model.dto.ErrorCodes;
import pro.beerpong.api.model.dto.ResponseEnvelope;
import pro.beerpong.api.service.GroupService;
import pro.beerpong.api.sockets.SocketEvent;
import pro.beerpong.api.sockets.SocketEventData;
import pro.beerpong.api.sockets.SubscriptionHandler;

@RestController
@RequestMapping("/groups/{groupId}")
@RequiredArgsConstructor
public class GroupAssetController {
private final GroupService groupService;
private final SubscriptionHandler subscriptionHandler;

@PutMapping("/wallpaper")
public ResponseEntity<ResponseEnvelope<AssetMetadataDto>> setWallpaper(@PathVariable String groupId, HttpServletRequest request, @RequestBody byte[] content) {
Expand All @@ -24,6 +28,10 @@ public ResponseEntity<ResponseEnvelope<AssetMetadataDto>> setWallpaper(@PathVari
return ResponseEnvelope.notOk(HttpStatus.NOT_FOUND, ErrorCodes.GROUP_NOT_FOUND);
}

return ResponseEnvelope.ok(groupService.storeWallpaper(group, content, request.getContentType()));
var dto = groupService.storeWallpaper(group, content, request.getContentType());

subscriptionHandler.callEvent(new SocketEvent<>(SocketEventData.GROUP_WALLPAPER_SET, groupId, dto));

return ResponseEnvelope.ok(dto);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,24 @@
import org.springframework.web.bind.annotation.*;
import pro.beerpong.api.model.dto.AssetMetadataDto;
import pro.beerpong.api.model.dto.ErrorCodes;
import pro.beerpong.api.model.dto.ProfileAssetMetadataDto;
import pro.beerpong.api.model.dto.ResponseEnvelope;
import pro.beerpong.api.service.GroupService;
import pro.beerpong.api.service.ProfileService;
import pro.beerpong.api.sockets.SocketEvent;
import pro.beerpong.api.sockets.SocketEventData;
import pro.beerpong.api.sockets.SubscriptionHandler;

@RestController
@RequestMapping("/groups/{groupId}/profiles/{profileId}")
@RequiredArgsConstructor
public class ProfileAssetController {
private final GroupService groupService;
private final ProfileService profileService;
private final SubscriptionHandler subscriptionHandler;

@PutMapping("/avatar")
public ResponseEntity<ResponseEnvelope<AssetMetadataDto>> setAvatar(@PathVariable String groupId, @PathVariable String profileId, HttpServletRequest request, @RequestBody byte[] content) {
public ResponseEntity<ResponseEnvelope<ProfileAssetMetadataDto>> setAvatar(@PathVariable String groupId, @PathVariable String profileId, HttpServletRequest request, @RequestBody byte[] content) {
var group = groupService.getGroupById(groupId);

if (group == null) {
Expand All @@ -32,6 +37,10 @@ public ResponseEntity<ResponseEnvelope<AssetMetadataDto>> setAvatar(@PathVariabl
return ResponseEnvelope.notOk(HttpStatus.NOT_FOUND, ErrorCodes.PROFILE_NOT_FOUND);
}

return ResponseEnvelope.ok(profileService.storeProfilePicture(profile, content, request.getContentType()));
var dto = new ProfileAssetMetadataDto(profileService.storeProfilePicture(profile, content, request.getContentType()), profileId);

subscriptionHandler.callEvent(new SocketEvent<>(SocketEventData.PROFILE_AVATAR_SET, groupId, dto));

return ResponseEnvelope.ok(dto);
}
}
20 changes: 13 additions & 7 deletions api/src/main/java/pro/beerpong/api/control/ProfileController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package pro.beerpong.api.control;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -10,27 +11,30 @@
import pro.beerpong.api.model.dto.ResponseEnvelope;
import pro.beerpong.api.service.GroupService;
import pro.beerpong.api.service.ProfileService;
import pro.beerpong.api.sockets.SocketEvent;
import pro.beerpong.api.sockets.SocketEventData;
import pro.beerpong.api.sockets.SubscriptionHandler;

import java.util.List;

@RestController
@RequestMapping("/groups/{groupId}/profiles")
@RequiredArgsConstructor
public class ProfileController {
private final GroupService groupService;
private final ProfileService profileService;

@Autowired
public ProfileController(GroupService groupService, ProfileService profileService) {
this.groupService = groupService;
this.profileService = profileService;
}
private final SubscriptionHandler subscriptionHandler;

@PostMapping
public ResponseEntity<ResponseEnvelope<ProfileDto>> createProfile(@PathVariable String groupId, @RequestBody ProfileCreateDto profileCreateDto) {
var group = groupService.getGroupById(groupId);

if (group != null) {
return ResponseEnvelope.ok(profileService.createProfile(groupId, profileCreateDto));
var dto = profileService.createProfile(groupId, profileCreateDto);

subscriptionHandler.callEvent(new SocketEvent<>(SocketEventData.PROFILE_CREATE, groupId, dto));

return ResponseEnvelope.ok(dto);
} else {
return ResponseEnvelope.notOk(HttpStatus.NOT_FOUND, ErrorCodes.GROUP_NOT_FOUND);
}
Expand Down Expand Up @@ -72,6 +76,8 @@ public ResponseEntity<ResponseEnvelope<ProfileDto>> updateProfile(@PathVariable
var updatedProfile = profileService.updateProfile(id, profileCreateDto);

if (updatedProfile != null) {
subscriptionHandler.callEvent(new SocketEvent<>(SocketEventData.PROFILE_UPDATE, groupId, updatedProfile));

return ResponseEnvelope.ok(updatedProfile);
} else {
return ResponseEnvelope.notOk(HttpStatus.NOT_FOUND, ErrorCodes.PROFILE_NOT_FOUND);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package pro.beerpong.api.model.dto;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.ZonedDateTime;

@Data
public class ProfileAssetMetadataDto {
private String profileId;
private String id;
private String url;
private String mediaType;
private ZonedDateTime uploadedAt;

public ProfileAssetMetadataDto(AssetMetadataDto dto, String profileId) {
this.profileId = profileId;
this.id = dto.getId();
this.url = dto.getUrl();
this.mediaType = dto.getMediaType();
this.uploadedAt = dto.getUploadedAt();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pro.beerpong.api.mapping.ProfileMapper;
import pro.beerpong.api.model.dao.Profile;
import pro.beerpong.api.model.dto.AssetMetadataDto;
import pro.beerpong.api.model.dto.ProfileAssetMetadataDto;
import pro.beerpong.api.model.dto.ProfileCreateDto;
import pro.beerpong.api.model.dto.ProfileDto;
import pro.beerpong.api.repository.GroupRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ public class SocketEventData<T> {

public static final SocketEventData<SeasonStartDto> SEASON_START = new SocketEventData<>(SeasonStartDto.class, SocketEventType.SEASONS, "seasonStart");

public static final SocketEventData<ProfileAssetMetadataDto> PROFILE_AVATAR_SET = new SocketEventData<>(ProfileAssetMetadataDto.class, SocketEventType.ASSETS, "profileAvatarSet");
public static final SocketEventData<AssetMetadataDto> GROUP_WALLPAPER_SET = new SocketEventData<>(AssetMetadataDto.class, SocketEventType.ASSETS, "groupWallpaperSet");

public static final SocketEventData<ProfileDto> PROFILE_CREATE = new SocketEventData<>(ProfileDto.class, SocketEventType.PROFILES, "profileCreate");
public static final SocketEventData<ProfileDto> PROFILE_UPDATE = new SocketEventData<>(ProfileDto.class, SocketEventType.PROFILES, "profileUpdate");

private final Class<T> bodyClass;
private final SocketEventType eventType;
private final String scope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ public enum SocketEventType {
SEASONS,
GROUPS,
RULES,
RULE_MOVES
RULE_MOVES,
ASSETS,
PROFILES
}
23 changes: 22 additions & 1 deletion mobile-app/api/generated/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResponseEnvelopeAssetMetadataDto"
"$ref": "#/components/schemas/ResponseEnvelopeProfileAssetMetadataDto"
}
}
}
Expand Down Expand Up @@ -1180,6 +1180,27 @@
"playerId": { "type": "string" }
}
},
"ProfileAssetMetadataDto": {
"type": "object",
"properties": {
"profileId": { "type": "string" },
"id": { "type": "string" },
"url": { "type": "string" },
"mediaType": { "type": "string" },
"uploadedAt": { "type": "string", "format": "date-time" }
}
},
"ResponseEnvelopeProfileAssetMetadataDto": {
"type": "object",
"properties": {
"status": { "type": "string", "enum": ["OK", "ERROR"] },
"httpCode": { "type": "integer", "format": "int32" },
"data": {
"$ref": "#/components/schemas/ProfileAssetMetadataDto"
},
"error": { "$ref": "#/components/schemas/ErrorDetails" }
}
},
"ProfileCreateDto": {
"type": "object",
"properties": { "name": { "type": "string" } }
Expand Down
19 changes: 18 additions & 1 deletion mobile-app/openapi/openapi.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ declare namespace Components {
points?: number; // int64
matches?: number; // int64
}
export interface ProfileAssetMetadataDto {
profileId?: string;
id?: string;
url?: string;
mediaType?: string;
uploadedAt?: string; // date-time
}
export interface ProfileCreateDto {
name?: string;
}
Expand Down Expand Up @@ -131,6 +138,12 @@ declare namespace Components {
data?: MatchDto;
error?: ErrorDetails;
}
export interface ResponseEnvelopeProfileAssetMetadataDto {
status?: 'OK' | 'ERROR';
httpCode?: number; // int32
data?: ProfileAssetMetadataDto;
error?: ErrorDetails;
}
export interface ResponseEnvelopeProfileDto {
status?: 'OK' | 'ERROR';
httpCode?: number; // int32
Expand Down Expand Up @@ -470,7 +483,7 @@ declare namespace Paths {
export type RequestBody = string; // byte
namespace Responses {
export type $200 =
Components.Schemas.ResponseEnvelopeAssetMetadataDto;
Components.Schemas.ResponseEnvelopeProfileAssetMetadataDto;
}
}
namespace SetWallpaper {
Expand Down Expand Up @@ -1077,6 +1090,8 @@ export type MatchMoveDto = Components.Schemas.MatchMoveDto;
export type MatchMoveDtoComplete = Components.Schemas.MatchMoveDtoComplete;
export type PlayerDto = Components.Schemas.PlayerDto;
export type PlayerStatisticsDto = Components.Schemas.PlayerStatisticsDto;
export type ProfileAssetMetadataDto =
Components.Schemas.ProfileAssetMetadataDto;
export type ProfileCreateDto = Components.Schemas.ProfileCreateDto;
export type ProfileDto = Components.Schemas.ProfileDto;
export type ResponseEnvelopeAssetMetadataDto =
Expand All @@ -1097,6 +1112,8 @@ export type ResponseEnvelopeListSeasonDto =
Components.Schemas.ResponseEnvelopeListSeasonDto;
export type ResponseEnvelopeMatchDto =
Components.Schemas.ResponseEnvelopeMatchDto;
export type ResponseEnvelopeProfileAssetMetadataDto =
Components.Schemas.ResponseEnvelopeProfileAssetMetadataDto;
export type ResponseEnvelopeProfileDto =
Components.Schemas.ResponseEnvelopeProfileDto;
export type ResponseEnvelopeRuleMoveDto =
Expand Down

0 comments on commit 7aa8af7

Please sign in to comment.