Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions .github/workflows/cd-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,6 @@ jobs:
DB_NAME: ${{ secrets.DEV_DB_NAME }}
DB_USERNAME: ${{ secrets.DEV_DB_USERNAME }}
DB_PASSWORD: ${{ secrets.DEV_DB_PASSWORD }}
OAUTH_GOOGLE_CLIENT_ID: ${{ secrets.OAUTH_GOOGLE_CLIENT_ID }}
OAUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.OAUTH_GOOGLE_CLIENT_SECRET }}
OAUTH_KAKAO_CLIENT_ID: ${{ secrets.OAUTH_KAKAO_CLIENT_ID }}
OAUTH_KAKAO_CLIENT_SECRET: ${{ secrets.OAUTH_KAKAO_CLIENT_SECRET }}
APPLE_CLIENT_ID: ${{ secrets.DEV_OAUTH_APPLE_CLIENT_ID }}
APPLE_TEAM_ID: ${{ secrets.DEV_OAUTH_APPLE_TEAM_ID }}
APPLE_KEY_ID: ${{ secrets.DEV_OAUTH_APPLE_KEY_ID }}
Expand All @@ -164,7 +160,7 @@ jobs:
host: ${{ secrets.EC2_HOST_DEV }}
username: ${{ secrets.EC2_USER_DEV }}
key: ${{ secrets.EC2_SSH_KEY_DEV }}
envs: APP_VERSION,APP_IMAGE_TAG,GHCR_USERNAME,GHCR_TOKEN,DB_HOST,DB_PORT,DB_NAME,DB_USERNAME,DB_PASSWORD,OAUTH_GOOGLE_CLIENT_ID,OAUTH_GOOGLE_CLIENT_SECRET,OAUTH_KAKAO_CLIENT_ID,OAUTH_KAKAO_CLIENT_SECRET,APPLE_CLIENT_ID,APPLE_TEAM_ID,APPLE_KEY_ID,APPLE_PRIVATE_KEY_BASE64,DEV_R2_PUBLIC_BASE_URL,DEV_R2_ENDPOINT,DEV_R2_BUCKET,DEV_R2_ACCESS_KEY,DEV_R2_SECRET_KEY
envs: APP_VERSION,APP_IMAGE_TAG,GHCR_USERNAME,GHCR_TOKEN,DB_HOST,DB_PORT,DB_NAME,DB_USERNAME,DB_PASSWORD,APPLE_CLIENT_ID,APPLE_TEAM_ID,APPLE_KEY_ID,APPLE_PRIVATE_KEY_BASE64,DEV_R2_PUBLIC_BASE_URL,DEV_R2_ENDPOINT,DEV_R2_BUCKET,DEV_R2_ACCESS_KEY,DEV_R2_SECRET_KEY
script: |
set -eu
cd /home/ubuntu/nalssilog-dev-api
Expand Down Expand Up @@ -197,10 +193,6 @@ jobs:
DEV_DB_URL=jdbc:postgresql://$DB_HOST:$DB_PORT/$DB_NAME?sslmode=require
DEV_DB_USERNAME=$DB_USERNAME
DEV_DB_PASSWORD=$DB_PASSWORD
OAUTH_GOOGLE_CLIENT_ID=${OAUTH_GOOGLE_CLIENT_ID:-dummy}
OAUTH_GOOGLE_CLIENT_SECRET=${OAUTH_GOOGLE_CLIENT_SECRET:-dummy}
OAUTH_KAKAO_CLIENT_ID=${OAUTH_KAKAO_CLIENT_ID:-dummy}
OAUTH_KAKAO_CLIENT_SECRET=${OAUTH_KAKAO_CLIENT_SECRET:-dummy}
OAUTH_APPLE_CLIENT_ID=${APPLE_CLIENT_ID:-}
OAUTH_APPLE_TEAM_ID=${APPLE_TEAM_ID:-}
OAUTH_APPLE_KEY_ID=${APPLE_KEY_ID:-}
Expand Down
10 changes: 1 addition & 9 deletions .github/workflows/cd-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,6 @@ jobs:
REDIS_HOST: ${{ secrets.PROD_REDIS_HOST }}
REDIS_PORT: ${{ secrets.PROD_REDIS_PORT }}
REDIS_PASSWORD: ${{ secrets.PROD_REDIS_PASSWORD }}
OAUTH_GOOGLE_CLIENT_ID: ${{ secrets.OAUTH_GOOGLE_CLIENT_ID }}
OAUTH_GOOGLE_CLIENT_SECRET: ${{ secrets.OAUTH_GOOGLE_CLIENT_SECRET }}
OAUTH_KAKAO_CLIENT_ID: ${{ secrets.OAUTH_KAKAO_CLIENT_ID }}
OAUTH_KAKAO_CLIENT_SECRET: ${{ secrets.OAUTH_KAKAO_CLIENT_SECRET }}
APPLE_CLIENT_ID: ${{ secrets.PROD_OAUTH_APPLE_CLIENT_ID }}
APPLE_TEAM_ID: ${{ secrets.PROD_OAUTH_APPLE_TEAM_ID }}
APPLE_KEY_ID: ${{ secrets.PROD_OAUTH_APPLE_KEY_ID }}
Expand All @@ -154,7 +150,7 @@ jobs:
host: ${{ secrets.EC2_HOST_PROD }}
username: ${{ secrets.EC2_USER_PROD }}
key: ${{ secrets.EC2_SSH_KEY_PROD }}
envs: APP_VERSION,APP_IMAGE_TAG,GHCR_USERNAME,GHCR_TOKEN,DB_HOST,DB_PORT,DB_NAME,DB_USERNAME,DB_PASSWORD,REDIS_HOST,REDIS_PORT,REDIS_PASSWORD,OAUTH_GOOGLE_CLIENT_ID,OAUTH_GOOGLE_CLIENT_SECRET,OAUTH_KAKAO_CLIENT_ID,OAUTH_KAKAO_CLIENT_SECRET,APPLE_CLIENT_ID,APPLE_TEAM_ID,APPLE_KEY_ID,APPLE_PRIVATE_KEY_BASE64,PROD_R2_PUBLIC_BASE_URL,PROD_R2_ENDPOINT,PROD_R2_BUCKET,PROD_R2_ACCESS_KEY,PROD_R2_SECRET_KEY
envs: APP_VERSION,APP_IMAGE_TAG,GHCR_USERNAME,GHCR_TOKEN,DB_HOST,DB_PORT,DB_NAME,DB_USERNAME,DB_PASSWORD,REDIS_HOST,REDIS_PORT,REDIS_PASSWORD,APPLE_CLIENT_ID,APPLE_TEAM_ID,APPLE_KEY_ID,APPLE_PRIVATE_KEY_BASE64,PROD_R2_PUBLIC_BASE_URL,PROD_R2_ENDPOINT,PROD_R2_BUCKET,PROD_R2_ACCESS_KEY,PROD_R2_SECRET_KEY
script: |
set -eu
cd /home/ubuntu/nalssilog-prod-api
Expand Down Expand Up @@ -190,10 +186,6 @@ jobs:
PROD_REDIS_HOST=$REDIS_HOST
PROD_REDIS_PORT=$REDIS_PORT
PROD_REDIS_PASSWORD=$REDIS_PASSWORD
OAUTH_GOOGLE_CLIENT_ID=${OAUTH_GOOGLE_CLIENT_ID:-dummy}
OAUTH_GOOGLE_CLIENT_SECRET=${OAUTH_GOOGLE_CLIENT_SECRET:-dummy}
OAUTH_KAKAO_CLIENT_ID=${OAUTH_KAKAO_CLIENT_ID:-dummy}
OAUTH_KAKAO_CLIENT_SECRET=${OAUTH_KAKAO_CLIENT_SECRET:-dummy}
OAUTH_APPLE_CLIENT_ID=${APPLE_CLIENT_ID:-}
OAUTH_APPLE_TEAM_ID=${APPLE_TEAM_ID:-}
OAUTH_APPLE_KEY_ID=${APPLE_KEY_ID:-}
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/resources/db/migration/V12__add_report_consents.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CREATE TABLE report_consent (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
report_id bigint NOT NULL,
terms_type character varying(20) NOT NULL,
version character varying(20) NOT NULL,
agreed_at timestamp(6) with time zone NOT NULL,
CONSTRAINT fk_report_consent_report
FOREIGN KEY (report_id)
REFERENCES weather_report (id)
ON DELETE CASCADE,
CONSTRAINT uk_report_consent_report_type
UNIQUE (report_id, terms_type),
CONSTRAINT chk_report_consent_terms_type
CHECK (terms_type IN ('SERVICE', 'PRIVACY'))
);

CREATE INDEX idx_report_consent_report
ON report_consent (report_id);
133 changes: 133 additions & 0 deletions app/src/main/resources/db/migration/V13__add_report_moderation.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
ALTER TABLE member
ADD COLUMN role character varying(20) NOT NULL DEFAULT 'MEMBER';

ALTER TABLE member
ADD CONSTRAINT chk_member_role
CHECK (role IN ('MEMBER', 'MODERATOR', 'ADMIN'));

CREATE TABLE member_role_change (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
target_member_id bigint NOT NULL,
changed_by_member_id bigint NOT NULL,
previous_role character varying(20) NOT NULL,
new_role character varying(20) NOT NULL,
CONSTRAINT chk_member_role_change_previous
CHECK (previous_role IN ('MEMBER', 'MODERATOR', 'ADMIN')),
CONSTRAINT chk_member_role_change_new
CHECK (new_role IN ('MEMBER', 'MODERATOR', 'ADMIN'))
);

CREATE INDEX idx_member_role_change_target
ON member_role_change (target_member_id, created_at);
CREATE INDEX idx_member_role_change_admin
ON member_role_change (changed_by_member_id, created_at);

ALTER TABLE weather_report
ADD COLUMN moderation_status character varying(20) NOT NULL DEFAULT 'VISIBLE';

ALTER TABLE weather_report
ADD CONSTRAINT chk_weather_report_moderation_status
CHECK (moderation_status IN ('VISIBLE', 'HIDDEN', 'REMOVED'));

CREATE INDEX idx_weather_report_visible_location_created
ON weather_report (location_id, created_at DESC, id DESC)
WHERE moderation_status = 'VISIBLE';

CREATE TABLE report_flag (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
report_id bigint NOT NULL,
reporter_type character varying(20) NOT NULL,
reporter_key character varying(64) NOT NULL,
reason character varying(30) NOT NULL,
detail character varying(500),
status character varying(20) NOT NULL,
processed_at timestamp(6) with time zone,
processed_by_member_id bigint,
resolution_note character varying(500),
CONSTRAINT fk_report_flag_report
FOREIGN KEY (report_id) REFERENCES weather_report (id) ON DELETE CASCADE,
CONSTRAINT uk_report_flag_report_reporter
UNIQUE (report_id, reporter_type, reporter_key),
CONSTRAINT chk_report_flag_reporter_type
CHECK (reporter_type IN ('MEMBER', 'ANONYMOUS')),
CONSTRAINT chk_report_flag_reason
CHECK (reason IN ('SPAM', 'ABUSE', 'HATE', 'SEXUAL', 'PRIVACY', 'FALSE_INFORMATION', 'OTHER')),
CONSTRAINT chk_report_flag_status
CHECK (status IN ('PENDING', 'RESOLVED', 'REJECTED'))
);

CREATE INDEX idx_report_flag_status_created
ON report_flag (status, created_at);
CREATE INDEX idx_report_flag_report
ON report_flag (report_id);

CREATE TABLE actor_block (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
blocker_type character varying(20) NOT NULL,
blocker_key character varying(64) NOT NULL,
blocked_type character varying(20) NOT NULL,
blocked_key character varying(64) NOT NULL,
CONSTRAINT uk_actor_block_pair
UNIQUE (blocker_type, blocker_key, blocked_type, blocked_key),
CONSTRAINT chk_actor_block_blocker_type
CHECK (blocker_type = 'MEMBER'),
CONSTRAINT chk_actor_block_blocked_type
CHECK (blocked_type = 'MEMBER')
);

CREATE INDEX idx_actor_block_blocker
ON actor_block (blocker_type, blocker_key);

CREATE TABLE actor_restriction (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
actor_type character varying(20) NOT NULL,
actor_key character varying(64) NOT NULL,
source_report_id bigint,
reason character varying(500) NOT NULL,
expires_at timestamp(6) with time zone,
created_by_member_id bigint NOT NULL,
lifted_at timestamp(6) with time zone,
lifted_by_member_id bigint,
CONSTRAINT fk_actor_restriction_source_report
FOREIGN KEY (source_report_id) REFERENCES weather_report (id) ON DELETE SET NULL,
CONSTRAINT chk_actor_restriction_actor_type
CHECK (actor_type IN ('MEMBER', 'ANONYMOUS'))
);

CREATE INDEX idx_actor_restriction_actor
ON actor_restriction (actor_type, actor_key, lifted_at, expires_at);

CREATE TABLE moderation_action (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
created_at timestamp(6) with time zone NOT NULL,
updated_at timestamp(6) with time zone NOT NULL,
action_type character varying(40) NOT NULL,
admin_member_id bigint NOT NULL,
report_id bigint,
target_actor_type character varying(20),
target_actor_key character varying(64),
reason character varying(500) NOT NULL,
CONSTRAINT fk_moderation_action_report
FOREIGN KEY (report_id) REFERENCES weather_report (id) ON DELETE SET NULL,
CONSTRAINT chk_moderation_action_type
CHECK (action_type IN (
'REPORT_HIDDEN', 'REPORT_RESTORED', 'REPORT_REMOVED',
'FLAG_RESOLVED', 'FLAG_REJECTED',
'AUTHOR_RESTRICTED', 'AUTHOR_RESTRICTION_LIFTED'
)),
CONSTRAINT chk_moderation_action_target_type
CHECK (target_actor_type IS NULL OR target_actor_type IN ('MEMBER', 'ANONYMOUS'))
);

CREATE INDEX idx_moderation_action_report
ON moderation_action (report_id, created_at);
CREATE INDEX idx_moderation_action_admin
ON moderation_action (admin_member_id, created_at);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE INDEX idx_actor_block_blocked
ON actor_block (blocked_type, blocked_key);
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.nalssilog.member.application.dto.SocialLoginResult;
import com.nalssilog.member.application.dto.TermsAgreement;
import com.nalssilog.member.domain.Provider;
import com.nalssilog.member.domain.MemberRole;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -49,6 +50,10 @@ public Optional<MemberInfo> findMemberInfo(Long memberId) {
return memberAccountService.findMemberInfo(memberId);
}

public Optional<MemberRole> findRole(Long memberId) {
return memberAccountService.findRole(memberId);
}

public Optional<MemberInfo> findMemberInfo(
Provider provider,
String providerUserId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ private static User user(MemberInfo member) {
return new User(
String.valueOf(member.id()),
member.nickname(),
new Avatar(member.avatarType(), member.avatarValue()));
new Avatar(member.avatarType(), member.avatarValue()),
member.role());
}
}
Loading