diff --git a/hasura/metadata/actions.yaml b/hasura/metadata/actions.yaml index 5092d0e..e038361 100644 --- a/hasura/metadata/actions.yaml +++ b/hasura/metadata/actions.yaml @@ -10,12 +10,6 @@ actions: email: '{{$body.input.email}}' template_engine: Kriti version: 2 - response_transform: - body: - action: transform - template: "{{ if $response.status == 200 }}\r\n {\r\n \"error\": {{$body.error}},\r\n \"message\": {{$body.message}}\r\n }\r\n{{ elif $response.status == 400 }}\r\n { \r\n \"message\": {{$body.error}}\r\n }\r\n{{ elif $response.status == 500 }}\r\n { \r\n \"message\": {{$response}}\r\n }\r\n{{ else }}\r\n { \r\n \"message\" : \"internal error\"\r\n }\r\n{{ end }}" - template_engine: Kriti - version: 2 comment: delete user custom_types: enums: [] diff --git a/hasura/metadata/backend_configs.yaml b/hasura/metadata/backend_configs.yaml index 1266c8d..0967ef4 100644 --- a/hasura/metadata/backend_configs.yaml +++ b/hasura/metadata/backend_configs.yaml @@ -1,11 +1 @@ -dataconnector: - athena: - uri: http://data-connector-agent:8081/api/v1/athena - mariadb: - uri: http://data-connector-agent:8081/api/v1/mariadb - mysql8: - uri: http://data-connector-agent:8081/api/v1/mysql - oracle: - uri: http://data-connector-agent:8081/api/v1/oracle - snowflake: - uri: http://data-connector-agent:8081/api/v1/snowflake +{} diff --git a/hasura/metadata/query_collections.yaml b/hasura/metadata/query_collections.yaml index 273adf1..9c07498 100644 --- a/hasura/metadata/query_collections.yaml +++ b/hasura/metadata/query_collections.yaml @@ -1038,70 +1038,6 @@ } } } - - name: User - Get Profile - query: | - query GetUserProfile { - authorizer_users(limit: 1) { - id - email - email_verified_at - bio - birthdate - gender - active_wallet_address: active_evm_address - wallet_address - nickname - picture - signup_methods - levels { - xp - level - user_level_chain { - id - name - punkga_config - } - } - authorizer_users_user_wallet { - address - } - user_quests_aggregate { - aggregate { - count - } - } - user_quests(order_by: {created_at:desc}, limit: 20) { - created_at - status - user_quest_rewards { - tx_hash - } - quest { - id - name - quests_campaign { - campaign_chain { - punkga_config - } - } - quests_i18n { - id - quest_id - language_id - data - i18n_language { - id - description - icon - is_main - symbol - } - } - reward - } - } - } - } - name: Public - Get manga by creator query: | query manga ($id: Int!, $limit: Int = 10, $offset: Int = 0) { @@ -1435,71 +1371,6 @@ } } } - - name: User - Get Profile - query: | - query GetUserProfile { - authorizer_users(limit: 1) { - id - email - email_verified_at - bio - birthdate - gender - active_wallet_address: active_evm_address - wallet_address - ton_wallet_address - nickname - picture - signup_methods - levels { - xp - level - user_level_chain { - id - name - punkga_config - } - } - authorizer_users_user_wallet { - address - } - user_quests_aggregate { - aggregate { - count - } - } - user_quests(order_by: {created_at:desc}, limit: 20) { - created_at - status - user_quest_rewards { - tx_hash - } - quest { - id - name - quests_campaign { - campaign_chain { - punkga_config - } - } - quests_i18n { - id - quest_id - language_id - data - i18n_language { - id - description - icon - is_main - symbol - } - } - reward - } - } - } - } - name: Admin - Query List Manga query: | query QueryListManga { @@ -1666,3 +1537,73 @@ created_at } } + - name: User - Get Profile + query: | + query GetUserProfile { + authorizer_users(limit: 1) { + id + email + email_verified_at + bio + birthdate + gender + active_wallet_address: active_evm_address + wallet_address + nickname + picture + signup_methods + levels { + xp + level + user_level_chain { + id + name + punkga_config + } + } + authorizer_users_user_wallet { + address + } + creator { + id + pen_name + avatar_url + bio + } + user_quests_aggregate { + aggregate { + count + } + } + user_quests(order_by: {created_at:desc}, limit: 20) { + created_at + status + user_quest_rewards { + tx_hash + } + quest { + id + name + quests_campaign { + campaign_chain { + punkga_config + } + } + quests_i18n { + id + quest_id + language_id + data + i18n_language { + id + description + icon + is_main + symbol + } + } + reward + } + } + } + } diff --git a/src/modules/user/dto/create-artist-request.dto.ts b/src/modules/user/dto/create-artist-request.dto.ts new file mode 100644 index 0000000..fb4fce0 --- /dev/null +++ b/src/modules/user/dto/create-artist-request.dto.ts @@ -0,0 +1,15 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class CreateArtistRequestDto { + @ApiProperty() + pen_name: string; + + @ApiProperty() + bio: string; + + @ApiPropertyOptional() + avatar_url: string; + + @ApiPropertyOptional({ type: 'string', format: 'binary' }) + avatar: Express.Multer.File; +} diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index d4424e2..5661e43 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -24,11 +24,12 @@ import { UpdateProfileRequestDto } from './dto/update-profile-request.dto'; import { UserService } from './user.service'; import { ReadChapterRequestDto } from './dto/read-chapter-request.dto'; import { ConnectWalletRequestDto } from './dto/connect-wallet-request.dto'; +import { CreateArtistRequestDto } from './dto/create-artist-request.dto'; @Controller('user') @ApiTags('user') export class UserController { - constructor(private readonly userSvc: UserService) { } + constructor(private readonly userSvc: UserService) {} @UseGuards(AuthGuard, RolesGuard) @ApiBearerAuth() @@ -78,4 +79,17 @@ export class UserController { getAvailableQuests() { return this.userSvc.getUserAvailableQuest(); } + + @UseGuards(AuthGuard, RolesGuard) + @ApiBearerAuth() + @Roles(Role.User) + @Post('artist') + @ApiConsumes('multipart/form-data') + @UseInterceptors(AuthUserInterceptor, AnyFilesInterceptor()) + createArtistProfile( + @Body() data: CreateArtistRequestDto, + @UploadedFiles() files: Array + ) { + return this.userSvc.createArtistProfile(data, files); + } } diff --git a/src/modules/user/user.graphql.ts b/src/modules/user/user.graphql.ts index b81175a..f11854c 100644 --- a/src/modules/user/user.graphql.ts +++ b/src/modules/user/user.graphql.ts @@ -379,4 +379,51 @@ export class UserGraphql { headers ); } + + createArtistProfile(variables: any) { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + + return this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `mutation insert_creators_one($object: creators_insert_input = {}) { + insert_creators_one(object: $object) { + id + email + gender + } + } + `, + 'insert_creators_one', + variables, + headers + ); + } + + async getUserInfo(variables: any) { + const headers = { + 'x-hasura-admin-secret': this.configSvc.get( + 'graphql.adminSecret' + ), + }; + + const result = await this.graphqlSvc.query( + this.configSvc.get('graphql.endpoint'), + '', + `query authorizer_users_by_pk($id: bpchar!) { + authorizer_users_by_pk(id: $id) { + email + } + }`, + 'authorizer_users_by_pk', + variables, + headers + ); + + return result.data.authorizer_users_by_pk; + } } diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 4a95187..87204c9 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -289,4 +289,42 @@ export class UserService { }; } } + + async createArtistProfile(data: any, files: Array) { + const { userId, token } = ContextProvider.getAuthUser(); + + // get user email + const user = await this.userGraphql.getUserInfo({ + id: userId, + }); + + const { pen_name, bio, avatar_url } = data; + let avatarUrl = data.avatar_url; + if (!avatar_url) { + // upload image + const avatar = files.find( + (file) => file.fieldname === 'avatar' && file.mimetype.includes('image') + ); + + // resize + const resized = await this.filesService.resize(avatar.buffer); + const s3SubFolder = + this.configService.get('aws.s3SubFolder') || 'images'; + const keyName = `${s3SubFolder}/user-${userId}/avatar.png`; + await this.filesService.uploadToS3(keyName, resized, 'image/png'); + + const s3Endpoint = this.configService.get('aws.queryEndpoint'); + avatarUrl = new URL(keyName, s3Endpoint).href; + } + + // create artist profile + return this.userGraphql.createArtistProfile({ + object: { + pen_name, + bio, + avatar_url: avatarUrl, + email: user.email, + }, + }); + } }