diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..619ded06 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +.PHONY: dev dev-down build test clean + +# 启动本地开发环境(仅依赖服务) +dev: + docker compose up -d + @echo "Waiting for services to be healthy..." + @sleep 5 + @echo "Services ready. Start backend with: cd server && ./mvnw spring-boot:run -Dspring-boot.run.profiles=local" + +# 停止本地开发环境 +dev-down: + docker compose down + +# 构建后端 +build: + cd server && ./mvnw clean package -DskipTests + +# 运行测试 +test: + cd server && ./mvnw test + +# 清理构建产物 +clean: + cd server && ./mvnw clean + docker compose down -v + +# 生成 OpenAPI 类型(前端用,Phase 1 暂不实现) +generate-api: + @echo "Frontend not yet implemented" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..63b0e8e8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,47 @@ +services: + postgres: + image: postgres:16-alpine + ports: + - "5432:5432" + environment: + POSTGRES_DB: skillhub + POSTGRES_USER: skillhub + POSTGRES_PASSWORD: skillhub_dev + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U skillhub"] + interval: 5s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + ports: + - "6379:6379" + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + + minio: + image: minio/minio:latest + ports: + - "9000:9000" + - "9001:9001" + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 5s + timeout: 5s + retries: 5 + +volumes: + postgres_data: + minio_data: diff --git a/server/pom.xml b/server/pom.xml index aa44ca3f..6a167777 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -12,7 +12,7 @@ - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT pom @@ -36,27 +36,27 @@ - com.skillhub + com.iflytek.skillhub skillhub-domain ${project.version} - com.skillhub + com.iflytek.skillhub skillhub-auth ${project.version} - com.skillhub + com.iflytek.skillhub skillhub-search ${project.version} - com.skillhub + com.iflytek.skillhub skillhub-storage ${project.version} - com.skillhub + com.iflytek.skillhub skillhub-infra ${project.version} diff --git a/server/skillhub-app/pom.xml b/server/skillhub-app/pom.xml index f80badea..2cd5a376 100644 --- a/server/skillhub-app/pom.xml +++ b/server/skillhub-app/pom.xml @@ -6,7 +6,7 @@ 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT @@ -28,15 +28,15 @@ 2.3.0 - com.skillhub + com.iflytek.skillhub skillhub-domain - com.skillhub + com.iflytek.skillhub skillhub-auth - com.skillhub + com.iflytek.skillhub skillhub-infra @@ -70,6 +70,11 @@ spring-boot-starter-test test + + com.h2database + h2 + test + diff --git a/server/skillhub-app/src/main/java/com/skillhub/SkillhubApplication.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/SkillhubApplication.java similarity index 90% rename from server/skillhub-app/src/main/java/com/skillhub/SkillhubApplication.java rename to server/skillhub-app/src/main/java/com/iflytek/skillhub/SkillhubApplication.java index 6c5c5d38..b85d9caa 100644 --- a/server/skillhub-app/src/main/java/com/skillhub/SkillhubApplication.java +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/SkillhubApplication.java @@ -1,4 +1,4 @@ -package com.skillhub; +package com.iflytek.skillhub; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/OpenApiConfig.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/OpenApiConfig.java new file mode 100644 index 00000000..e45f3c7f --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/OpenApiConfig.java @@ -0,0 +1,25 @@ +package com.iflytek.skillhub.config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.servers.Server; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class OpenApiConfig { + + @Bean + public OpenAPI skillhubOpenAPI() { + return new OpenAPI() + .info(new Info() + .title("SkillHub API") + .description("Skills Registry Platform") + .version("0.1.0")) + .servers(List.of( + new Server().url("http://localhost:8080").description("Local development") + )); + } +} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/SecurityConfig.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/SecurityConfig.java new file mode 100644 index 00000000..29b14f7e --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/config/SecurityConfig.java @@ -0,0 +1,22 @@ +package com.iflytek.skillhub.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(auth -> auth + .requestMatchers("/api/v1/health", "/actuator/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll() + .anyRequest().authenticated() + ); + return http.build(); + } +} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/HealthController.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/HealthController.java new file mode 100644 index 00000000..b1225f8c --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/HealthController.java @@ -0,0 +1,17 @@ +package com.iflytek.skillhub.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1") +public class HealthController { + + @GetMapping("/health") + public Map health() { + return Map.of("status", "UP"); + } +} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/ErrorResponse.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/ErrorResponse.java new file mode 100644 index 00000000..194b6861 --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/ErrorResponse.java @@ -0,0 +1,7 @@ +package com.iflytek.skillhub.dto; + +public record ErrorResponse( + int status, + String error, + String message +) {} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/exception/GlobalExceptionHandler.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..a8962949 --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/exception/GlobalExceptionHandler.java @@ -0,0 +1,27 @@ +package com.iflytek.skillhub.exception; + +import com.iflytek.skillhub.dto.ErrorResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(Exception.class) + public ResponseEntity handleGlobalException(Exception ex, WebRequest request) { + logger.error("Unhandled exception", ex); + ErrorResponse error = new ErrorResponse( + HttpStatus.INTERNAL_SERVER_ERROR.value(), + "Internal server error", + ex.getMessage() + ); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); + } +} diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestIdFilter.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestIdFilter.java new file mode 100644 index 00000000..e9dc6422 --- /dev/null +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestIdFilter.java @@ -0,0 +1,40 @@ +package com.iflytek.skillhub.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.MDC; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.UUID; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class RequestIdFilter extends OncePerRequestFilter { + + private static final String REQUEST_ID_HEADER = "X-Request-Id"; + private static final String REQUEST_ID_MDC_KEY = "requestId"; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String requestId = request.getHeader(REQUEST_ID_HEADER); + if (requestId == null || requestId.isBlank()) { + requestId = UUID.randomUUID().toString(); + } + + MDC.put(REQUEST_ID_MDC_KEY, requestId); + response.setHeader(REQUEST_ID_HEADER, requestId); + + try { + filterChain.doFilter(request, response); + } finally { + MDC.remove(REQUEST_ID_MDC_KEY); + } + } +} diff --git a/server/skillhub-app/src/main/resources/application-local.yml b/server/skillhub-app/src/main/resources/application-local.yml index 4cdcbe15..899183dc 100644 --- a/server/skillhub-app/src/main/resources/application-local.yml +++ b/server/skillhub-app/src/main/resources/application-local.yml @@ -16,5 +16,5 @@ spring: logging: level: - com.skillhub: DEBUG + com.iflytek.skillhub: DEBUG org.springframework.security: DEBUG diff --git a/server/skillhub-app/src/main/resources/db/migration/V1__init_schema.sql b/server/skillhub-app/src/main/resources/db/migration/V1__init_schema.sql new file mode 100644 index 00000000..86b4d9b4 --- /dev/null +++ b/server/skillhub-app/src/main/resources/db/migration/V1__init_schema.sql @@ -0,0 +1,164 @@ +-- Phase 1 核心表:认证与授权 + +-- 用户账号表 +CREATE TABLE user_account ( + id BIGSERIAL PRIMARY KEY, + display_name VARCHAR(128) NOT NULL, + email VARCHAR(256), + avatar_url VARCHAR(512), + status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', + merged_to_user_id BIGINT, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX idx_user_account_email ON user_account(email); +CREATE INDEX idx_user_account_status ON user_account(status); + +-- OAuth 身份绑定表 +CREATE TABLE identity_binding ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL REFERENCES user_account(id), + provider_code VARCHAR(64) NOT NULL, + subject VARCHAR(256) NOT NULL, + login_name VARCHAR(128), + extra_json JSONB, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(provider_code, subject) +); + +CREATE INDEX idx_identity_binding_user_id ON identity_binding(user_id); + +-- API Token 表 +CREATE TABLE api_token ( + id BIGSERIAL PRIMARY KEY, + subject_type VARCHAR(32) NOT NULL DEFAULT 'USER', + subject_id BIGINT NOT NULL, + user_id BIGINT NOT NULL REFERENCES user_account(id), + name VARCHAR(128) NOT NULL, + token_prefix VARCHAR(16) NOT NULL, + token_hash VARCHAR(64) NOT NULL UNIQUE, + scope_json JSONB NOT NULL, + expires_at TIMESTAMP, + last_used_at TIMESTAMP, + revoked_at TIMESTAMP, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX idx_api_token_user_id ON api_token(user_id); +CREATE INDEX idx_api_token_hash ON api_token(token_hash); + +-- 角色表 +CREATE TABLE role ( + id BIGSERIAL PRIMARY KEY, + code VARCHAR(64) NOT NULL UNIQUE, + name VARCHAR(128) NOT NULL, + description VARCHAR(512), + is_system BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- 权限表 +CREATE TABLE permission ( + id BIGSERIAL PRIMARY KEY, + code VARCHAR(128) NOT NULL UNIQUE, + name VARCHAR(128) NOT NULL, + group_code VARCHAR(64) +); + +-- 角色权限关联表 +CREATE TABLE role_permission ( + role_id BIGINT NOT NULL REFERENCES role(id), + permission_id BIGINT NOT NULL REFERENCES permission(id), + PRIMARY KEY (role_id, permission_id) +); + +-- 用户角色绑定表 +CREATE TABLE user_role_binding ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL REFERENCES user_account(id), + role_id BIGINT NOT NULL REFERENCES role(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(user_id, role_id) +); + +CREATE INDEX idx_user_role_binding_user_id ON user_role_binding(user_id); + +-- 命名空间表 +CREATE TABLE namespace ( + id BIGSERIAL PRIMARY KEY, + slug VARCHAR(64) NOT NULL UNIQUE, + display_name VARCHAR(128) NOT NULL, + type VARCHAR(32) NOT NULL, + description TEXT, + avatar_url VARCHAR(512), + status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', + created_by BIGINT REFERENCES user_account(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- 命名空间成员表 +CREATE TABLE namespace_member ( + id BIGSERIAL PRIMARY KEY, + namespace_id BIGINT NOT NULL REFERENCES namespace(id), + user_id BIGINT NOT NULL REFERENCES user_account(id), + role VARCHAR(32) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(namespace_id, user_id) +); + +CREATE INDEX idx_namespace_member_user_id ON namespace_member(user_id); +CREATE INDEX idx_namespace_member_namespace_id ON namespace_member(namespace_id); + +-- 审计日志表 +CREATE TABLE audit_log ( + id BIGSERIAL PRIMARY KEY, + actor_user_id BIGINT REFERENCES user_account(id), + action VARCHAR(64) NOT NULL, + target_type VARCHAR(64), + target_id BIGINT, + request_id VARCHAR(64), + client_ip VARCHAR(64), + user_agent VARCHAR(512), + detail_json JSONB, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX idx_audit_log_actor ON audit_log(actor_user_id); +CREATE INDEX idx_audit_log_created_at ON audit_log(created_at); +CREATE INDEX idx_audit_log_request_id ON audit_log(request_id); + +-- 插入系统内置角色 +INSERT INTO role (code, name, description, is_system) VALUES +('SUPER_ADMIN', '超级管理员', '拥有所有权限', TRUE), +('SKILL_ADMIN', '技能管理员', '全局空间审核、提升审核、隐藏/撤回', TRUE), +('USER_ADMIN', '用户管理员', '准入审批、封禁/解封、角色分配', TRUE), +('AUDITOR', '审计员', '查看审计日志', TRUE); + +-- 插入系统权限 +INSERT INTO permission (code, name, group_code) VALUES +('skill:publish', '发布技能', 'skill'), +('skill:manage', '管理技能', 'skill'), +('skill:promote', '提升到全局', 'skill'), +('review:approve', '审核技能', 'review'), +('promotion:approve', '审核提升申请', 'promotion'), +('user:manage', '管理用户', 'user'), +('user:approve', '审批用户准入', 'user'), +('audit:read', '查看审计日志', 'audit'); + +-- 绑定角色权限 +INSERT INTO role_permission (role_id, permission_id) +SELECT r.id, p.id FROM role r, permission p WHERE r.code = 'SKILL_ADMIN' AND p.code IN ('review:approve', 'skill:manage', 'promotion:approve'); + +INSERT INTO role_permission (role_id, permission_id) +SELECT r.id, p.id FROM role r, permission p WHERE r.code = 'USER_ADMIN' AND p.code IN ('user:manage', 'user:approve'); + +INSERT INTO role_permission (role_id, permission_id) +SELECT r.id, p.id FROM role r, permission p WHERE r.code = 'AUDITOR' AND p.code = 'audit:read'; + +-- 插入系统内置 @global 命名空间 +INSERT INTO namespace (slug, display_name, type, description, status) +VALUES ('global', 'Global', 'GLOBAL', 'Platform-level public namespace', 'ACTIVE'); diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/HealthControllerTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/HealthControllerTest.java new file mode 100644 index 00000000..49dd3083 --- /dev/null +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/controller/HealthControllerTest.java @@ -0,0 +1,28 @@ +package com.iflytek.skillhub.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles("test") +class HealthControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void shouldReturnHealthStatus() throws Exception { + mockMvc.perform(get("/api/v1/health")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("UP")); + } +} diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestIdFilterTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestIdFilterTest.java new file mode 100644 index 00000000..127059a4 --- /dev/null +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestIdFilterTest.java @@ -0,0 +1,37 @@ +package com.iflytek.skillhub.filter; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles("test") +class RequestIdFilterTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void shouldGenerateRequestIdWhenNotProvided() throws Exception { + mockMvc.perform(get("/actuator/health")) + .andExpect(status().isOk()) + .andExpect(header().exists("X-Request-Id")); + } + + @Test + void shouldPreserveProvidedRequestId() throws Exception { + String requestId = "test-request-123"; + mockMvc.perform(get("/actuator/health") + .header("X-Request-Id", requestId)) + .andExpect(status().isOk()) + .andExpect(header().string("X-Request-Id", requestId)); + } +} diff --git a/server/skillhub-app/src/test/resources/application-test.yml b/server/skillhub-app/src/test/resources/application-test.yml new file mode 100644 index 00000000..82988572 --- /dev/null +++ b/server/skillhub-app/src/test/resources/application-test.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + driver-class-name: org.h2.Driver + username: sa + password: + jpa: + hibernate: + ddl-auto: none + database-platform: org.hibernate.dialect.H2Dialect + flyway: + enabled: false + data: + redis: + host: localhost + port: 6379 + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration + - org.springframework.boot.autoconfigure.session.SessionAutoConfiguration diff --git a/server/skillhub-auth/pom.xml b/server/skillhub-auth/pom.xml index 851ace69..44f8bf7a 100644 --- a/server/skillhub-auth/pom.xml +++ b/server/skillhub-auth/pom.xml @@ -5,14 +5,14 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT skillhub-auth - com.skillhub + com.iflytek.skillhub skillhub-domain diff --git a/server/skillhub-domain/pom.xml b/server/skillhub-domain/pom.xml index 4629a580..32d91ae0 100644 --- a/server/skillhub-domain/pom.xml +++ b/server/skillhub-domain/pom.xml @@ -5,7 +5,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT diff --git a/server/skillhub-infra/pom.xml b/server/skillhub-infra/pom.xml index b000156a..04c21641 100644 --- a/server/skillhub-infra/pom.xml +++ b/server/skillhub-infra/pom.xml @@ -5,14 +5,14 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT skillhub-infra - com.skillhub + com.iflytek.skillhub skillhub-domain diff --git a/server/skillhub-search/pom.xml b/server/skillhub-search/pom.xml index 0ded25aa..adb323c2 100644 --- a/server/skillhub-search/pom.xml +++ b/server/skillhub-search/pom.xml @@ -5,14 +5,14 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT skillhub-search - com.skillhub + com.iflytek.skillhub skillhub-domain diff --git a/server/skillhub-storage/pom.xml b/server/skillhub-storage/pom.xml index 0d3d9762..19ea55a4 100644 --- a/server/skillhub-storage/pom.xml +++ b/server/skillhub-storage/pom.xml @@ -5,7 +5,7 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.skillhub + com.iflytek.skillhub skillhub-parent 0.1.0-SNAPSHOT