Controller
package controllers;
import com.avaje.ebean.Ebean;
import com.google.inject.Inject;
import controllers.integralCore.AbstractIntegralCoreController;
import dtos.blacklistIp.BlacklistIpDto;
import forms.blacklistIp.BlacklistIpDeleteForm;
import forms.blacklistIp.BlacklistIpGetForm;
import forms.blacklistIp.BlacklistIpPostForm;
import forms.blacklistIp.BlacklistIpPutForm;
import helpers.OperatorLoginAuthenticator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import models.entities.BlacklistIp;
import play.Logger;
import play.data.Form;
import play.data.FormFactory;
import play.data.validation.ValidationError;
import play.i18n.MessagesApi;
import play.mvc.BodyParser;
import play.mvc.Result;
import play.mvc.Security;
import services.BlacklistIpService;
import swagger.components.Responses.BlacklistIpDeleteResponse;
import swagger.components.Responses.BlacklistIpGetResponse;
import swagger.components.Responses.BlacklistIpPostResponse;
import swagger.components.Responses.BlacklistIpPutResponse;
import wrappers.ResultWrapper;
import java.util.ArrayList;
import java.util.List;
@Api(value = "BlacklistIp")
public class BlacklistIpController extends AbstractIntegralCoreController {
@Inject
private FormFactory formFactory;
@Inject
private BlacklistIpService blacklistIpService;
@Inject
private services.integralCore.BlacklistIpService blacklistIpIntegralCoreService;
@Inject
private BlacklistIpController(MessagesApi messagesApi) { super(messagesApi); }
/**
* ブラックリストIPを取得(1件)
*
* @param blacklistIpId
* @return
*/
@Security.Authenticated(OperatorLoginAuthenticator.class)
@ApiOperation(
nickname = "blacklistIp/read",
value = "Find an blacklistIp",
response = BlacklistIpGetResponse.class,
responseContainer = ""
)
public Result read(Long blacklistIpId) {
Form<BlacklistIpGetForm> blacklistIpGetForm = formFactory.form(BlacklistIpGetForm.class).bindFromRequest();
if (blacklistIpGetForm.hasErrors()) {
return badRequest(blacklistIpGetForm);
}
BlacklistIpGetForm form = blacklistIpGetForm.get();
// integral-core連携時
if (config.getBoolean("admiral.integralcoreEnabled")) {
models.entities.integralCore.BlacklistIp blacklistIp = blacklistIpIntegralCoreService.findById(blacklistIpId);
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpGetForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpGetForm>(blacklistIpDto, form);
return ok(result);
// デフォルト時
} else {
BlacklistIp blacklistIp = blacklistIpService.findById(blacklistIpId);
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpGetForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpGetForm>(blacklistIpDto, form);
return ok(result);
}
}
/**
* ブラックリストIPを登録
*
*/
@BodyParser.Of(BodyParser.Json.class)
@Security.Authenticated(OperatorLoginAuthenticator.class)
@ApiOperation(
nickname = "blacklistIp/create",
value = "Create a blacklistIp",
response = BlacklistIpPostResponse.class,
responseContainer = ""
)
@ApiImplicitParams({
@ApiImplicitParam(name = "body", dataType = "forms.blacklistIp.BlacklistIpPostForm", paramType = "body")
})
public Result create() {
// integral-core連携時
if (config.getBoolean("admiral.integralcoreEnabled")) {
models.entities.integralCore.BlacklistIp blacklistIp = null;
Form<BlacklistIpPostForm> blacklistIpPostForm = formFactory.form(BlacklistIpPostForm.class).bindFromRequest();
if (blacklistIpPostForm.hasErrors()) {
return badRequest(blacklistIpPostForm);
}
BlacklistIpPostForm form = blacklistIpPostForm.get();
List<ValidationError> errors = validateBlacklistIpIntegralCoreCreation(form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
db().beginTransaction();
try {
blacklistIp = blacklistIpIntegralCoreService.insertBlacklistIpIntegralCore(form.getIpAddress(), form.getNote());
if (blacklistIp == null || blacklistIp.getBlacklistIpId() == null) {
throw new RuntimeException("error.failed");
}
db().commitTransaction();
} catch (Exception e) {
db().rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
db().endTransaction();
}
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpPostForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpPostForm>(blacklistIpDto, form);
return ok(result);
// デフォルト時
} else {
BlacklistIp blacklistIp = null;
Form<BlacklistIpPostForm> blacklistIpPostForm = formFactory.form(BlacklistIpPostForm.class).bindFromRequest();
if (blacklistIpPostForm.hasErrors()) {
return badRequest(blacklistIpPostForm);
}
BlacklistIpPostForm form = blacklistIpPostForm.get();
List<ValidationError> errors = validateBlacklistIpCreation(form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
Ebean.beginTransaction();
try {
blacklistIp = blacklistIpService.insertBlacklistIp(form.getIpAddress(), form.getNote());
if (blacklistIp == null || blacklistIp.getBlacklistIpId() == null) {
throw new RuntimeException("error.failed");
}
Ebean.commitTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
Ebean.endTransaction();
}
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpPostForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpPostForm>(blacklistIpDto, form);
return ok(result);
}
}
/**
* 登録時のDBまわりのバリデーション Integralcore連携時
*
* @param form
* @return errors
*/
private List<ValidationError> validateBlacklistIpIntegralCoreCreation(BlacklistIpPostForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
return errors;
}
/**
* 登録時のDBまわりのバリデーション デフォルト時
*
* @param form
* @return errors
*/
private List<ValidationError> validateBlacklistIpCreation(BlacklistIpPostForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
return errors;
}
/**
* ブラックリストIPを更新
* @param blacklistIpId
*/
@BodyParser.Of(BodyParser.Json.class)
@Security.Authenticated(OperatorLoginAuthenticator.class)
@ApiOperation(
nickname = "blacklistIp/update",
value = "Update a blacklistIp",
response = BlacklistIpPutResponse.class,
responseContainer = ""
)
@ApiImplicitParams({
@ApiImplicitParam(name = "body", dataType = "forms.blacklistIp.BlacklistIpPutForm", paramType = "body")
})
public Result update(Long blacklistIpId) {
// integral-core連携時
if (config.getBoolean("admiral.integralcoreEnabled")){
models.entities.integralCore.BlacklistIp blacklistIp = null;
Form<BlacklistIpPutForm> blacklistIpIntegralCorePutForm = formFactory.form(BlacklistIpPutForm.class).bindFromRequest();
if (blacklistIpIntegralCorePutForm.hasErrors()) {
return badRequest(blacklistIpIntegralCorePutForm);
}
BlacklistIpPutForm form = blacklistIpIntegralCorePutForm.get();
List<ValidationError> errors = validateBlacklistIpIntegralCoreUpdation(blacklistIpId, form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
db().beginTransaction();
try {
blacklistIp = blacklistIpIntegralCoreService.updateBlacklistIpIntegralCore(blacklistIpId, form.getIpAddress(), form.getNote());
if (blacklistIp == null || blacklistIp.getBlacklistIpId() == null) {
throw new RuntimeException("更新処理に失敗しました");
}
db().commitTransaction();
} catch (Exception e) {
db().rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
db().endTransaction();
}
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpPutForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpPutForm>(blacklistIpDto, form);
return ok(result);
// デフォルト時
} else {
BlacklistIp blacklistIp = null;
Form<BlacklistIpPutForm> blacklistIpPutForm = formFactory.form(BlacklistIpPutForm.class).bindFromRequest();
if (blacklistIpPutForm.hasErrors()) {
return badRequest(blacklistIpPutForm);
}
BlacklistIpPutForm form = blacklistIpPutForm.get();
List<ValidationError> errors = validateBlacklistIpUpdation(blacklistIpId, form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
Ebean.beginTransaction();
try {
blacklistIp = blacklistIpService.updateBlacklistIp(blacklistIpId, form.getIpAddress(), form.getNote());
if (blacklistIp == null || blacklistIp.getBlacklistIpId() == null) {
throw new RuntimeException("更新処理に失敗しました");
}
Ebean.commitTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
Ebean.endTransaction();
}
BlacklistIpDto blacklistIpDto = new BlacklistIpDto(blacklistIp);
ResultWrapper<BlacklistIpDto, BlacklistIpPutForm> result = new ResultWrapper<BlacklistIpDto, BlacklistIpPutForm>(blacklistIpDto, form);
return ok(result);
}
}
/**
* 更新時のDBまわりのバリデーション integral-core連携時
*
* @param BlacklistIpId
* @param form
* @return errors
*/
private List<ValidationError> validateBlacklistIpIntegralCoreUpdation(long BlacklistIpId, BlacklistIpPutForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
models.entities.integralCore.BlacklistIp blacklistIp = blacklistIpIntegralCoreService.findById(BlacklistIpId);
// 存在チェック
if (blacklistIp == null) {
errors.add(new ValidationError("error", "error.notFound"));
}
return errors;
}
/**
* 更新時のDBまわりのバリデーション デフォルト時
*
* @param BlacklistIpId
* @param form
* @return errors
*/
private List<ValidationError> validateBlacklistIpUpdation(long BlacklistIpId, BlacklistIpPutForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
BlacklistIp blacklistIp = blacklistIpService.findById(BlacklistIpId);
// 存在チェック
if (blacklistIp == null) {
errors.add(new ValidationError("error", "error.notFound"));
}
return errors;
}
/**
* ブラックリストIPを削除
*
* @param blacklistIpId
*/
@Security.Authenticated(OperatorLoginAuthenticator.class)
@ApiOperation(
nickname = "blacklistIp/delete",
value = "Delete an blacklistIp",
response = BlacklistIpDeleteResponse.class,
responseContainer = ""
)
@ApiImplicitParams({
@ApiImplicitParam(name = "body", dataType = "forms.blacklistIp.BlacklistIpDeleteForm", paramType = "body")
})
public Result delete(Long blacklistIpId) {
// integral-core連携時
if (config.getBoolean("admiral.integralcoreEnabled")) {
Form<BlacklistIpDeleteForm> blacklistIpIntegralCoreDeleteForm = formFactory.form(BlacklistIpDeleteForm.class).bindFromRequest();
if (blacklistIpIntegralCoreDeleteForm.hasErrors()) {
return badRequest(blacklistIpIntegralCoreDeleteForm);
}
BlacklistIpDeleteForm form = blacklistIpIntegralCoreDeleteForm.get();
List<ValidationError> errors = validateBlacklistIpIntegralCoreDeletion(blacklistIpId, form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
db().beginTransaction();
try {
// ブラックリストIPの削除
blacklistIpIntegralCoreService.deleteBlacklistIpIntegralCore(blacklistIpId);
db().commitTransaction();
} catch (Exception e) {
db().rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
db().endTransaction();
}
return ok("{}");
// デフォルト時
} else {
Form<BlacklistIpDeleteForm> blacklistIpDeleteForm = formFactory.form(BlacklistIpDeleteForm.class).bindFromRequest();
if (blacklistIpDeleteForm.hasErrors()) {
return badRequest(blacklistIpDeleteForm);
}
BlacklistIpDeleteForm form = blacklistIpDeleteForm.get();
List<ValidationError> errors = validateBlacklistIpDeletion(blacklistIpId, form);
if (!errors.isEmpty()) {
return badRequest(errors);
}
// トランザクション開始
Ebean.beginTransaction();
try {
// ブラックリストIPの削除
blacklistIpService.deleteBlacklistIp(blacklistIpId);
Ebean.commitTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
Logger.error("e = {}", e);
return internalServerError("error.failed");
} finally {
Ebean.endTransaction();
}
return ok("{}");
}
}
/**
* 削除時のDBまわりのバリデーション integral-core連携時
*
* @param blacklistIpId
* @return errors
*/
private List<ValidationError> validateBlacklistIpIntegralCoreDeletion(Long blacklistIpId, BlacklistIpDeleteForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
models.entities.integralCore.BlacklistIp blacklistIp = blacklistIpIntegralCoreService.findById(blacklistIpId);
// 存在チェック
if (blacklistIp == null) {
errors.add(new ValidationError("error", "error.notFound"));
}
return errors;
}
/**
* 削除時のDBまわりのバリデーション デフォルト時
*
* @param blacklistIpId
* @return errors
*/
private List<ValidationError> validateBlacklistIpDeletion(Long blacklistIpId, BlacklistIpDeleteForm form) {
List<ValidationError> errors = new ArrayList<ValidationError>();
BlacklistIp blacklistIp = blacklistIpService.findById(blacklistIpId);
// 存在チェック
if (blacklistIp == null) {
errors.add(new ValidationError("error", "error.notFound"));
}
return errors;
}
}
DTO
package dtos.blacklistIp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import models.entities.BlacklistIp;
@Data
@ApiModel(value = "blacklistIp.BlacklistIpDto")
public class BlacklistIpDto {
public BlacklistIpDto(BlacklistIp blacklistIp) {
this.blacklistIpId = blacklistIp.getBlacklistIpId();
this.ipAddress = blacklistIp.getIpAddress();
this.note = blacklistIp.getNote();
}
public BlacklistIpDto(models.entities.integralCore.BlacklistIp blacklistIp) {
this.blacklistIpId = blacklistIp.getBlacklistIpId();
this.ipAddress = blacklistIp.getIpAddress();
this.note = blacklistIp.getNote();
}
private Long blacklistIpId;
private String ipAddress;
private String note;
}
Form(putのみ)
package forms.blacklistIp;
import forms.AbstractForm;
import lombok.Data;
import play.data.validation.Constraints.Pattern;
import play.data.validation.Constraints.MaxLength;
@Data
public class BlacklistIpPutForm extends AbstractForm {
@Pattern(message = "error.invalid", value = "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")
private String ipAddress;
@MaxLength(value = 255, message = "error.maxLength")
private String note;
}
Service
package services;
import java.util.Optional;
import com.avaje.ebean.PagedList;
import com.google.inject.Inject;
import dtos.PagingDto;
import models.daos.BlacklistIpDao;
import models.entities.BlacklistIp;
import play.Logger;
public class BlacklistIpService extends AbstractService {
@Inject
private BlacklistIpDao blacklistIpDao;
/**
* ブラックリストIPをIDで検索する
*
* @param blacklistIpId
* @return
*/
public BlacklistIp findById(Long blacklistIpId) { return blacklistIpDao.findById(blacklistIpId, false); }
/**
* ブラックリストIP一覧の検索を取得する
*
* @param pagingDto
* @param withDeleted
*/
public PagedList<BlacklistIp> findBlacklistIps(PagingDto pagingDto, Boolean withDeleted) {
String orderby = pagingDto.orderby;
String sort = pagingDto.sort;
int page = pagingDto.page;
int limit = pagingDto.limit;
if(withDeleted == null) {
withDeleted = false;
}
return blacklistIpDao.findBlacklistIps(orderby, sort, page, limit, withDeleted);
}
/**
* ブラックリストIPを新規登録する
*
* @param ipAddress
* @param note
* @return blacklistIp
*/
public BlacklistIp insertBlacklistIp(String ipAddress, String note) {
BlacklistIp blacklistIp = new BlacklistIp();
blacklistIp.setIpAddress(ipAddress);
blacklistIp.setNote(note);
blacklistIpDao.insert(blacklistIp);
if (blacklistIp.getBlacklistIpId() == null) {
blacklistIp = null;
}
return blacklistIp;
}
/**
* ブラックリストIPを更新する
*
* @param blacklistIpId
* @param ipAddress
* @param note
* @return blacklist
*/
public BlacklistIp updateBlacklistIp(long blacklistIpId, String ipAddress, String note) {
BlacklistIp blacklistIp = findById(blacklistIpId);
if (blacklistIp == null) {
Logger.error("対象が見つかりません. blacklistIp = {}", blacklistIp);
return null;
}
Optional.ofNullable(ipAddress).ifPresent(v -> blacklistIp.setIpAddress(v));
Optional.ofNullable(note).ifPresent(v -> blacklistIp.setNote(v));
blacklistIpDao.update(blacklistIp);
return blacklistIp;
}
/**
* ブラックリストIPを削除する
*
* @param blacklistIpId
*/
public void deleteBlacklistIp(Long blacklistIpId) {
BlacklistIp blacklistIp = findById(blacklistIpId);
if (blacklistIp == null) {
return;
}
blacklistIpDao.delete(blacklistIp);
return;
}
}
Dao
package models.daos;
import models.entities.BlacklistIp;
import org.apache.commons.lang3.BooleanUtils;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.Query;
import com.google.common.base.CaseFormat;
import enums.ORDER;
public class BlacklistIpDao extends AbstractDao<BlacklistIp> {
/**
* IDを指定してブラックリストIPを取得
*
* @param blacklistIpId
* @returm blacklist
* */
public BlacklistIp findById(Long blacklistIpId, Boolean withDeleted) {
Query<BlacklistIp> query = Ebean.find(BlacklistIp.class)
.where()
.eq("blacklistIpId", new Long(blacklistIpId))
.query();
if (BooleanUtils.isTrue(withDeleted)) {
query = query.setIncludeSoftDeletes();
}
BlacklistIp blacklistIp = query.findUnique();
return blacklistIp;
}
/**
* ブラックリストIP一覧を検索する
*
* @param orderby
* @param sort
* @param limit
* @param page
* @param withDeleted
*/
public PagedList<BlacklistIp> findBlacklistIps(String orderby, String sort, int page, int limit, boolean withDeleted) {
String tmpOrderby = null;
Query<BlacklistIp> query = null;
ExpressionList<BlacklistIp> el = Ebean.find(BlacklistIp.class).where();
tmpOrderby = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, orderby);
if (tmpOrderby.split("\\.").length == 1) {
tmpOrderby = "t0." + tmpOrderby;
}
if (ORDER.DESC.getType().equals(sort)) {
query = el.order().desc(tmpOrderby);
} else {
query = el.order().asc(tmpOrderby);
}
// 削除済みを含むかどうか
if (withDeleted) {
query = query.setIncludeSoftDeletes();
}
PagedList<BlacklistIp> pagedList = query.setFirstRow((page - 1) * limit).setMaxRows(limit).findPagedList();
return pagedList;
}
/**
* ブラックリストIPを登録する
*
* @param blacklistIp
*/
public void insert(BlacklistIp blacklistIp) {
if (blacklistIp == null) {
return;
}
blacklistIp.insert();
}
/**
* ブラックリストIPを更新する
*
* @param blacklistIp
*/
public void update(BlacklistIp blacklistIp) {
if (blacklistIp == null) {
return;
}
blacklistIp.update();
}
/**
* ブラックリストIPを削除する
*
* @param blacklistIp
*/
public void delete(BlacklistIp blacklistIp) {
if (blacklistIp == null) {
return;
}
blacklistIp.delete();
}
}
Entity
package models.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@Table(name = "blacklist_ip")
public class BlacklistIp extends BaseEntity<BlacklistIp> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(precision = 20, nullable = false, unique = true)
private Long blacklistIpId;
@Column(length = 255, nullable = false, unique = false)
private String ipAddress;
@Column(length = 255 ,nullable = true, unique = false)
private String note;
@Override
public int hashCode(){
return this.blacklistIpId == null ? 0 : this.blacklistIpId.intValue();
}
}
BaseEntity
package models.entities;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import com.avaje.ebean.Model;
import com.avaje.ebean.annotation.SoftDelete;
import com.avaje.ebean.annotation.WhenCreated;
import com.avaje.ebean.annotation.WhenModified;
import com.avaje.ebean.annotation.WhoCreated;
import com.avaje.ebean.annotation.WhoModified;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.event.ServerConfigStartup;
import com.fasterxml.jackson.annotation.JsonIgnore;
import ebean.CurrentAccountIdProviderImpl;
@MappedSuperclass
public class BaseEntity<T> extends Model implements ServerConfigStartup {
@Override
public void onStart(ServerConfig serverConfig) {
serverConfig.setCurrentUserProvider(new CurrentAccountIdProviderImpl());
}
/**
* 削除フラグ
*/
@SoftDelete
@Column(nullable = false, unique = false)
public boolean deleted;
/**
* バージョン
*/
@JsonIgnore
@Version
@Column(nullable = false, unique = false)
public int version;
/**
* 作成者ID
*/
@JsonIgnore
@WhoCreated
@Column(precision = 20, nullable = false, unique = false)
public Long createdBy;
/**
* 作成日
*/
@JsonIgnore
@WhenCreated
@Column(nullable = false, unique = false)
public LocalDateTime createdAt;
/**
* 更新者ID
*/
@JsonIgnore
@WhoModified
@Column(precision = 20, nullable = false, unique = false)
public Long updatedBy;
/**
* 更新日
*/
@JsonIgnore
@WhenModified
@Column(nullable = false, unique = false)
public LocalDateTime updatedAt;
/**
* 日付フォーマット
*/
@JsonIgnore
final protected DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
}
コメント