chore: 调整项目结构
diff --git a/admin-bff/bff/.gitignore b/admin-bff/bff/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/admin-bff/bff/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/admin-bff/bff/Dockerfile b/admin-bff/bff/Dockerfile
new file mode 100644
index 0000000..b91c9f4
--- /dev/null
+++ b/admin-bff/bff/Dockerfile
@@ -0,0 +1,21 @@
+FROM harbor.supwisdom.com/institute/openjdk:8-jre-alpine
+
+ENV ENABLE_JMX_SSL=false
+ENV JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker
+ENV SPRING_PROFILES_ACTIVE=docker
+
+ARG NAME
+ARG VERSION
+ARG JAR_FILE
+
+LABEL name=$NAME \
+      version=$VERSION
+
+EXPOSE 8080
+
+EXPOSE 8443
+
+COPY --chown=java-app:java-app target/${JAR_FILE} /home/java-app/lib/app.jar
+
+# COPY --chown=java-app:java-app target/doc /home/java-app/doc
+# COPY --chown=java-app:java-app target/api-docs /home/java-app/api-docs
diff --git a/admin-bff/bff/pom.xml b/admin-bff/bff/pom.xml
new file mode 100644
index 0000000..81e4eb9
--- /dev/null
+++ b/admin-bff/bff/pom.xml
@@ -0,0 +1,216 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.supwisdom.institute</groupId>
+    <artifactId>sw-backend-admin-bff-parent</artifactId>
+    <version>0.0.2-SNAPSHOT</version>
+  </parent>
+
+  <groupId>com.supwisdom.institute</groupId>
+  <artifactId>sw-backend-admin-bff</artifactId>
+  <version>0.0.2-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Supwisdom Backend Framework Admin Backend for Frontend</name>
+  <description>Supwisdom Backend Framework Admin Backend for Frontend project</description>
+
+  <properties>
+    <start-class>com.supwisdom.institute.backend.admin.bff.Application</start-class>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+    </dependency>
+
+    <!-- 微服务 健康监控 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-actuator</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-openfeign</artifactId>
+    </dependency>
+    <!-- openfeign's dependency -->
+    <dependency>
+      <groupId>com.netflix.feign</groupId>
+      <artifactId>feign-httpclient</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpcore</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-online-doc</artifactId>
+    </dependency>
+
+
+    <!-- <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-mvc</artifactId>
+    </dependency> -->
+
+    <!-- <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-object-mapper</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-i18n</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-lang</artifactId>
+    </dependency> -->
+
+
+    <dependency>
+      <groupId>com.supwisdom.institute</groupId>
+      <artifactId>sw-backend-common-framework</artifactId>
+    </dependency>
+    
+    
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger-ui</artifactId>
+    </dependency>
+
+
+    <!-- 热部署,无需重启项目 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-devtools</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <finalName>${project.artifactId}</finalName>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-release-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
+
+
+      <!-- <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>2.4.3</version>
+        <configuration>
+          <encoding>${project.build.sourceEncoding}</encoding>
+        </configuration>
+        <executions>
+          <execution>
+            <id>copy-doc-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/doc</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../doc</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-api-docs-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/api-docs</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../api-docs</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin> -->
+
+
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <groupId>com.spotify</groupId>
+        <artifactId>dockerfile-maven-plugin</artifactId>
+        <configuration>
+          <skip>false</skip>
+        </configuration>
+      </plugin>
+
+    </plugins>
+
+  </build>
+
+</project>
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java
new file mode 100644
index 0000000..64ea622
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java
@@ -0,0 +1,28 @@
+package com.supwisdom.institute.backend.admin.bff;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+import com.supwisdom.infras.online.doc.configuration.EnableInfrasOnlineDoc;
+import com.supwisdom.institute.backend.common.core.transmit.annotation.EnableSimpleUserTransmit;
+import com.supwisdom.institute.backend.common.framework.exception.EnableCustomExceptionHandler;
+
+@SpringBootApplication
+@EnableFeignClients
+
+@EnableScheduling
+
+@EnableSimpleUserTransmit
+
+@EnableCustomExceptionHandler
+
+@EnableInfrasOnlineDoc
+public class Application {
+
+  public static void main(String[] args) {
+    SpringApplication.run(Application.class, args);
+  }
+  
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/autorefesh/base/InMemeryPermissionRoleSetAutoRefresh.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/autorefesh/base/InMemeryPermissionRoleSetAutoRefresh.java
new file mode 100644
index 0000000..d149eee
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/autorefesh/base/InMemeryPermissionRoleSetAutoRefresh.java
@@ -0,0 +1,26 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.autorefesh.base;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.service.base.AuthnService;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Component
+public class InMemeryPermissionRoleSetAutoRefresh {
+
+  @Autowired
+  private AuthnService authnService;
+  
+  @Scheduled(initialDelayString = "${inMemeryPermissionRoleSetAutoRefresh.schedule.startDelay:500}",
+      fixedDelayString = "${inMemeryPermissionRoleSetAutoRefresh.schedule.repeatInterval:20000}")
+  public void refresh() {
+    log.info("InMemeryPermissionRoleSetAutoRefresh, refresh permissionRoleSets");
+    
+    authnService.loadPermissionRoleSets();
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/.gitkeep b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/.gitkeep
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/base/AdminBaseController.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/base/AdminBaseController.java
new file mode 100644
index 0000000..6224970
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/base/AdminBaseController.java
@@ -0,0 +1,19 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.controller.base;
+
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+@RestController
+@RequestMapping(value = "/v1/admin/base")
+public class AdminBaseController {
+  
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String hello() {
+    return "hello, " + UserContext.getUsername();
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/biz/AdminBizController.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/biz/AdminBizController.java
new file mode 100644
index 0000000..8c46261
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/biz/AdminBizController.java
@@ -0,0 +1,26 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.controller.biz;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.service.biz.BizService;
+
+@RestController
+@RequestMapping(value = "/v1/admin/biz")
+public class AdminBizController {
+  
+  @Autowired
+  BizService bizService;
+
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String biz() {
+    
+    bizService.query(true, -1, -1);
+    
+    return "biz";
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/me/MeController.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/me/MeController.java
new file mode 100644
index 0000000..c88e7c5
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/me/MeController.java
@@ -0,0 +1,79 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.controller.me;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Permission;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.me.CurrentUser;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.me.GrantedMenu;
+import com.supwisdom.institute.backend.admin.bff.api.v1.service.base.AuthnService;
+import com.supwisdom.institute.backend.admin.bff.api.v1.vo.me.response.data.CurrentUserResponseData;
+import com.supwisdom.institute.backend.admin.bff.api.v1.vo.me.response.data.GrantedMenusResponseData;
+import com.supwisdom.institute.backend.admin.bff.utils.CurrentUserUtil;
+import com.supwisdom.institute.backend.common.core.transmit.user.User;
+import com.supwisdom.institute.backend.common.framework.entity.EntityUtils;
+import com.supwisdom.institute.backend.common.framework.vo.response.DefaultApiResponse;
+
+
+@Api(value = "BFFMe", tags = { "me" }, description = "登录用户相关信息的接口")
+@RestController
+@RequestMapping(value = "/v1/me")
+public class MeController {
+  
+  @Autowired
+  private AuthnService authnService;
+  
+  @ApiOperation(
+      tags = { "me" },
+      value = "获取登录用户的基本信息", notes = "获取登录用户的基本信息", nickname = "user"
+  )
+  @RequestMapping(method = RequestMethod.GET, path = "/user", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public DefaultApiResponse<CurrentUserResponseData> user() {
+    
+    User user = CurrentUserUtil.currentUser();
+    
+    CurrentUser cu = new CurrentUser();
+    cu.setUsername(user.getUsername());
+    cu.setRoles(user.getRoles());
+    cu.setAttributes(user.getAttributes());
+    
+    // XXX: 如果需要放入其他信息,可以扩展CurrentUser,并从服务接口中获取后写入数据
+    
+    CurrentUserResponseData data = CurrentUserResponseData.of(cu);
+    return new DefaultApiResponse<CurrentUserResponseData>(data);
+  }
+  
+  @ApiOperation(
+      tags = { "me" },
+      value = "获取登录用户的访问菜单", notes = "获取登录用户的访问菜单", nickname = "accountMenus"
+  )
+  @RequestMapping(method = RequestMethod.GET, path = "/menus", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public DefaultApiResponse<GrantedMenusResponseData> accountMenus() {
+    
+    String username = CurrentUserUtil.currentUsername();
+    
+    List<Permission> menus =  authnService.menus(username, "1");  // XXX: applicationId
+    
+    List<GrantedMenu> grantedMenus = new ArrayList<>();
+    
+    menus.forEach(m -> {
+      GrantedMenu grantedMenu = new GrantedMenu();
+      grantedMenu = EntityUtils.copy(m, grantedMenu);
+      grantedMenus.add(grantedMenu);
+    });
+    
+    GrantedMenusResponseData data = GrantedMenusResponseData.of(grantedMenus);
+    return new DefaultApiResponse<GrantedMenusResponseData>(data);
+    
+  }
+  
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenController.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenController.java
new file mode 100644
index 0000000..1b04e65
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenController.java
@@ -0,0 +1,53 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.controller.open;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.PermissionRoleSet;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.open.Menu;
+import com.supwisdom.institute.backend.admin.bff.api.v1.service.base.AuthnService;
+import com.supwisdom.institute.backend.admin.bff.api.v1.vo.open.response.data.MenusResponseData;
+import com.supwisdom.institute.backend.common.framework.vo.response.DefaultApiResponse;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(value = "BFFOpen", tags = { "open" }, description = "公开接口")
+@RestController
+@RequestMapping(value = "/v1/open")
+public class OpenController {
+  
+  @Autowired
+  private AuthnService authnService;
+  
+  @ApiOperation(
+      tags = { "open" },
+      value = "获取菜单", notes = "获取菜单", nickname = "openMenus"
+  )
+  @RequestMapping(method = RequestMethod.GET, path = "/menus", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public DefaultApiResponse<MenusResponseData> menus() {
+    
+    List<Menu> menus = new ArrayList<>();
+
+    List<PermissionRoleSet> permissionRoleSets = authnService.getPermissionRoleSets("1"); // XXX: applicationId
+    if (permissionRoleSets != null) {
+      for (PermissionRoleSet permissionRoleSet : permissionRoleSets) {
+        Menu menu = new Menu();
+        BeanUtils.copyProperties(permissionRoleSet, menu);
+        menus.add(menu);
+      }
+    }
+    
+    MenusResponseData data = MenusResponseData.of(menus);
+    return new DefaultApiResponse<MenusResponseData>(data);
+  }
+  
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenSyncController.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenSyncController.java
new file mode 100644
index 0000000..ab6da53
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/controller/open/OpenSyncController.java
@@ -0,0 +1,55 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.controller.open;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Role;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.open.SyncRoleModel;
+import com.supwisdom.institute.backend.admin.bff.api.v1.service.base.AuthnService;
+import com.supwisdom.institute.backend.admin.bff.api.v1.vo.open.response.data.OpenSyncRolesResponseData;
+import com.supwisdom.institute.backend.common.framework.vo.response.DefaultApiResponse;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(value = "BFFOpen", tags = { "open" }, description = "公开接口")
+@RestController
+@RequestMapping(value = "/v1/open/sync")
+public class OpenSyncController {
+
+  @Autowired
+  private AuthnService authnService;
+
+  @ApiOperation(
+      tags = { "open" },
+      value = "获取角色", notes = "获取角色", nickname = "openRoles"
+  )
+  @RequestMapping(method = RequestMethod.GET, path = "/roles", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public DefaultApiResponse<OpenSyncRolesResponseData> roles(
+      @RequestParam(name = "applicationId", required = true) String applicationId) {
+    
+    List<SyncRoleModel> syncRoleModels = new ArrayList<>();
+
+    List<Role> systemRoles = authnService.roles();
+    for (Role systemRole : systemRoles) {
+      SyncRoleModel syncRoleModel = new SyncRoleModel(
+          systemRole.getId(), 
+          systemRole.getCode(),
+          systemRole.getName(),
+          systemRole.getMemo());
+      syncRoleModels.add(syncRoleModel);
+    }
+    
+    OpenSyncRolesResponseData data = OpenSyncRolesResponseData.of(applicationId, syncRoleModels);
+    return new DefaultApiResponse<OpenSyncRolesResponseData>(data);
+  }
+  
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/.gitkeep b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/.gitkeep
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Account.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Account.java
new file mode 100644
index 0000000..ebb0513
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Account.java
@@ -0,0 +1,70 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Account extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -4889952442290543101L;
+
+  private String id;
+
+  /**
+   * 用户名
+   */
+  private String username;
+  
+  /**
+   * 密码
+   */
+  private String password;
+
+  /**
+   * 是否可用,1 可用,0 不可用,默认:1
+   */
+  private Boolean enabled;
+  /**
+   * 账号未过期,1 未过期,0 过期,默认:1
+   */
+  private Boolean accountNonExpired;
+  /**
+   * 账号未锁定,1 未锁定,0 锁定,默认:1
+   */
+  private Boolean accountNonLocked;
+  /**
+   * 密码未过期,1 未过期,0 过期,默认:1
+   */
+  private Boolean credentialsNonExpired;
+
+  /**
+   * 姓名
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+  /**
+   * 登录手机
+   */
+  private String mobile;
+  /**
+   * 登录邮箱
+   */
+  private String email;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Application.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Application.java
new file mode 100644
index 0000000..b0f6c48
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Application.java
@@ -0,0 +1,39 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Application extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 7687658763529677076L;
+
+  private String id;
+  
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Permission.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Permission.java
new file mode 100644
index 0000000..5877bf9
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Permission.java
@@ -0,0 +1,69 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Permission extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -3042842657207449148L;
+
+  private String id;
+
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+  /**
+   * 菜单图标
+   */
+  private String icon;
+
+  /**
+   * 类型(1 应用,2 菜单,3 操作)
+   */
+  private String type;
+
+  /**
+   * URL地址
+   */
+  private String url;
+
+  /**
+   * 系统ID
+   */
+  private String applicationId;
+
+  /**
+   * 父级ID
+   */
+  private String parentId;
+
+  /**
+   * 排序
+   */
+  private Integer order;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/PermissionRoleSet.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/PermissionRoleSet.java
new file mode 100644
index 0000000..6080107
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/PermissionRoleSet.java
@@ -0,0 +1,114 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class PermissionRoleSet extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -1482739465611090145L;
+  
+  @Getter
+  @Setter
+  private String id;
+
+  /**
+   * 代码
+   */
+  @Getter
+  @Setter
+  private String code;
+
+  /**
+   * 名称
+   */
+  @Getter
+  @Setter
+  private String name;
+
+  /**
+   * 备注
+   */
+  @Getter
+  @Setter
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  @Getter
+  @Setter
+  private String status;
+
+  /**
+   * 类型(1 应用,2 菜单,3 操作)
+   */
+  @Getter
+  @Setter
+  private String type;
+
+  /**
+   * 菜单图标
+   */
+  @Getter
+  @Setter
+  private String icon;
+
+  /**
+   * URL地址
+   */
+  @Getter
+  @Setter
+  private String url;
+
+  /**
+   * 系统ID
+   */
+  @Getter
+  @Setter
+  private String applicationId;
+
+  /**
+   * 父级ID
+   */
+  @Getter
+  @Setter
+  private String parentId;
+
+  /**
+   * 排序
+   */
+  @Getter
+  @Setter
+  private Integer order;
+
+  @Getter
+  @Setter
+  private Collection<Role> roles;
+  
+  private Collection<String> permissionRoles = null;
+  public boolean matches(Collection<String> userRoles) {
+    if (permissionRoles == null) {
+      permissionRoles = new ArrayList<String>();
+      Iterator<Role> it = roles.iterator();
+      while (it.hasNext()) {
+        Role r = it.next();
+        permissionRoles.add(r.getCode());
+      }
+    }
+    
+    userRoles.retainAll(permissionRoles);
+    
+    return !userRoles.isEmpty();
+  }
+  
+  
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/ResourceRoleSet.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/ResourceRoleSet.java
new file mode 100644
index 0000000..665154d
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/ResourceRoleSet.java
@@ -0,0 +1,80 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import java.util.Collection;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class ResourceRoleSet extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -683204173918706673L;
+
+  public static final String ACCESS_ANONYMOUS = "anonymous"; // 匿名访问anonymous
+  public static final String ACCESS_AUTHENTICATE = "authenticate"; // 认证访问authenticate
+  public static final String ACCESS_AUTHORIZE = "authorize"; // 授权访问authorize
+  public static final String ACCESS_PERMIT_ALL = "permitAll"; // 允许所有permitAll
+  public static final String ACCESS_DENY_ALL = "denyAll"; // 拒绝所有denyAll
+
+  @Getter
+  @Setter
+  private String id;
+
+  /**
+   * 代码
+   */
+  @Getter
+  @Setter
+  private String code;
+
+  /**
+   * 名称
+   */
+  @Getter
+  @Setter
+  private String name;
+
+  /**
+   * 备注
+   */
+  @Getter
+  @Setter
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  @Getter
+  @Setter
+  private String status;
+
+  /**
+   * 请求方式(GET、POST、PUT、DELETE 等)
+   */
+  @Getter
+  @Setter
+  private String method;
+
+  /**
+   * 请求路径
+   */
+  @Getter
+  @Setter
+  private String path;
+
+  /**
+   * 访问规则(匿名访问anonymous、认证访问authenticate、授权访问authorize、允许所有permitAll、拒绝所有denyAll)
+   */
+  @Getter
+  @Setter
+  private String access;
+
+  @Getter
+  @Setter
+  Collection<Role> roles;
+  
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Role.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Role.java
new file mode 100644
index 0000000..d8c5144
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/base/Role.java
@@ -0,0 +1,39 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.base;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+@Getter
+@Setter
+public class Role extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -8551951601186240995L;
+
+  private String id;
+
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/biz/Biz.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/biz/Biz.java
new file mode 100644
index 0000000..a290125
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/biz/Biz.java
@@ -0,0 +1,37 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.biz;
+
+import java.util.Date;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+public class Biz extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 8755876583168251137L;
+  
+  @Getter
+  @Setter
+  private String id;
+
+  @Getter
+  @Setter
+  private String name;
+  
+  @Getter
+  @Setter
+  private Boolean bool;
+  
+  @Getter
+  @Setter
+  private Date date;
+
+  @Getter
+  @Setter
+  private Integer num;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/CurrentUser.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/CurrentUser.java
new file mode 100644
index 0000000..3563b30
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/CurrentUser.java
@@ -0,0 +1,30 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.me;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+public class CurrentUser extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 2049212615500816301L;
+  
+  @Getter
+  @Setter
+  private String username;
+  
+  @Getter
+  @Setter
+  private List<String> roles;
+  
+  @Getter
+  @Setter
+  private Map<String, Object> attributes;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/GrantedMenu.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/GrantedMenu.java
new file mode 100644
index 0000000..5d8cd70
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/me/GrantedMenu.java
@@ -0,0 +1,64 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.me;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class GrantedMenu extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -1261755008133562980L;
+
+  private String id;
+
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+  /**
+   * 菜单图标
+   */
+  private String icon;
+
+  /**
+   * URL地址
+   */
+  private String url;
+
+  /**
+   * 系统ID
+   */
+  private String applicationId;
+
+  /**
+   * 父级ID
+   */
+  private String parentId;
+
+  /**
+   * 排序
+   */
+  private Integer order;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/Menu.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/Menu.java
new file mode 100644
index 0000000..b3bdc99
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/Menu.java
@@ -0,0 +1,64 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.open;
+
+import com.supwisdom.institute.backend.common.framework.model.ABaseModel;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Menu extends ABaseModel {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 4206010261706882919L;
+  
+  private String id;
+
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 备注
+   */
+  private String memo;
+
+  /**
+   * 状态(1 启用,0 停用)
+   */
+  private String status;
+
+  /**
+   * 菜单图标
+   */
+  private String icon;
+
+  /**
+   * URL地址
+   */
+  private String url;
+
+  /**
+   * 系统ID
+   */
+  private String applicationId;
+
+  /**
+   * 父级ID
+   */
+  private String parentId;
+
+  /**
+   * 排序
+   */
+  private Integer order;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/SyncRoleModel.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/SyncRoleModel.java
new file mode 100644
index 0000000..72986bc
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/model/open/SyncRoleModel.java
@@ -0,0 +1,39 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.model.open;
+
+import java.io.Serializable;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class SyncRoleModel implements Serializable {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -1916611618482825238L;
+  
+  /**
+   * ID
+   */
+  private String id;
+
+  /**
+   * 代码
+   */
+  private String code;
+
+  /**
+   * 名称
+   */
+  private String name;
+
+  /**
+   * 描述
+   */
+  private String memo;
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/.gitkeep b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/.gitkeep
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/configuration/BaseFeignClientConfiguration.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/configuration/BaseFeignClientConfiguration.java
new file mode 100644
index 0000000..da7040b
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/configuration/BaseFeignClientConfiguration.java
@@ -0,0 +1,36 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.base.configuration;
+
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
+import org.springframework.context.annotation.Bean;
+
+import com.supwisdom.institute.backend.common.core.feign.FeignClientBuilder;
+
+import feign.Client;
+
+public class BaseFeignClientConfiguration {
+
+  @Bean
+  public Client feignClient(
+      @Value("${sw-backend-base-api.client-auth.enabled:false}") boolean enabled,
+      @Value("${sw-backend-base-api.client-auth.key-password:}") String keyPassword,
+      @Value("${sw-backend-base-api.client-auth.key-store:}") String keyStore,
+      @Value("${sw-backend-base-api.client-auth.key-store-password:}") String keyStorePassword,
+      @Value("${sw-backend-base-api.client-auth.trust-store:}") String trustStore,
+      @Value("${sw-backend-base-api.client-auth.trust-store-password:}") String trustStorePassword,
+      ApacheHttpClientFactory httpClientFactory,
+      HttpClientConnectionManager httpClientConnectionManager) {
+    
+    return FeignClientBuilder.builder()
+        .enabled(enabled)
+        .keyPassword(keyPassword)
+        .keyStore(keyStore)
+        .keyStorePassword(keyStorePassword)
+        .trustStore(trustStore)
+        .trustStorePassword(trustStorePassword)
+        .build()
+        .apacheHttpClient(httpClientFactory, httpClientConnectionManager);
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFallbackFactory.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFallbackFactory.java
new file mode 100644
index 0000000..e965dab
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFallbackFactory.java
@@ -0,0 +1,101 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.base.v1.authn;
+
+import org.springframework.stereotype.Component;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.exception.FallbackError;
+
+import feign.hystrix.FallbackFactory;
+
+@Component
+public class AuthnRemoteFallbackFactory implements FallbackFactory<AuthnRemoteFeignClient> {
+
+  @Override
+  public AuthnRemoteFeignClient create(Throwable cause) {
+    return new AuthnRemoteFeignClient() {
+
+      @Override
+      public JSONObject account(String username) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject roles(String username) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject applications(String username, String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject menus(String username, String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject operations(String username, String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject resources(String username, String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+      
+
+      @Override
+      public JSONObject applications() {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject roles() {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject permissionRoleSets(String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject resourceRoleSets(String applicationId) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+      
+    };
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFeignClient.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFeignClient.java
new file mode 100644
index 0000000..0486ffd
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/base/v1/authn/AuthnRemoteFeignClient.java
@@ -0,0 +1,64 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.base.v1.authn;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.base.configuration.BaseFeignClientConfiguration;
+
+@FeignClient(
+    configuration = {BaseFeignClientConfiguration.class},
+    name = "base-admin-account-remote-feign-client",
+    url = "${sw-backend-base-api.uri}/v1/authn",
+    fallbackFactory = AuthnRemoteFallbackFactory.class
+)
+public interface AuthnRemoteFeignClient {
+  
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/account")
+  JSONObject account(
+      @PathVariable(name = "username") String username);
+
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/roles")
+  JSONObject roles(
+      @PathVariable(name = "username") String username);
+
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/applications")
+  JSONObject applications(
+      @PathVariable(name = "username") String username,
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/menus")
+  JSONObject menus(
+      @PathVariable(name = "username") String username,
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/operations")
+  JSONObject operations(
+      @PathVariable(name = "username") String username,
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+
+  @RequestMapping(method = RequestMethod.GET, path = "/{username}/resources")
+  JSONObject resources(
+      @PathVariable(name = "username") String username,
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+
+  @RequestMapping(method = RequestMethod.GET, path = "/applications")
+  JSONObject applications();
+  
+  @RequestMapping(method = RequestMethod.GET, path = "/roles")
+  JSONObject roles();
+
+  @RequestMapping(method = RequestMethod.GET, path = "/permissionRoleSets")
+  JSONObject permissionRoleSets(
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+  @RequestMapping(method = RequestMethod.GET, path = "/resourceRoleSets")
+  JSONObject resourceRoleSets(
+      @RequestParam(name = "applicationId", required = false) String applicationId);
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/configuration/BizFeignClientConfiguration.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/configuration/BizFeignClientConfiguration.java
new file mode 100644
index 0000000..1e031d0
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/configuration/BizFeignClientConfiguration.java
@@ -0,0 +1,36 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.biz.configuration;
+
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
+import org.springframework.context.annotation.Bean;
+
+import com.supwisdom.institute.backend.common.core.feign.FeignClientBuilder;
+
+import feign.Client;
+
+public class BizFeignClientConfiguration {
+
+  @Bean
+  public Client feignClient(
+      @Value("${sw-backend-biz-api.client-auth.enabled:false}") boolean enabled,
+      @Value("${sw-backend-biz-api.client-auth.key-password:}") String keyPassword,
+      @Value("${sw-backend-biz-api.client-auth.key-store:}") String keyStore,
+      @Value("${sw-backend-biz-api.client-auth.key-store-password:}") String keyStorePassword,
+      @Value("${sw-backend-biz-api.client-auth.trust-store:}") String trustStore,
+      @Value("${sw-backend-biz-api.client-auth.trust-store-password:}") String trustStorePassword,
+      ApacheHttpClientFactory httpClientFactory,
+      HttpClientConnectionManager httpClientConnectionManager) {
+    
+    return FeignClientBuilder.builder()
+      .enabled(enabled)
+      .keyPassword(keyPassword)
+      .keyStore(keyStore)
+      .keyStorePassword(keyStorePassword)
+      .trustStore(trustStore)
+      .trustStorePassword(trustStorePassword)
+      .build()
+      .apacheHttpClient(httpClientFactory, httpClientConnectionManager);
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFallbackFactory.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFallbackFactory.java
new file mode 100644
index 0000000..c73d3ee
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFallbackFactory.java
@@ -0,0 +1,61 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.biz.v1.admin;
+
+import org.springframework.stereotype.Component;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.biz.Biz;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.exception.FallbackError;
+
+import feign.hystrix.FallbackFactory;
+
+@Component
+public class AdminBizRemoteFallbackFactory implements FallbackFactory<AdminBizRemoteFeignClient> {
+
+  @Override
+  public AdminBizRemoteFeignClient create(Throwable cause) {
+    return new AdminBizRemoteFeignClient() {
+
+      @Override
+      public JSONObject query(boolean loadAll, int pageIndex, int pageSize) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject load(String id) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject create(Biz biz) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject update(String id, Biz biz) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+
+      @Override
+      public JSONObject delete(String id) {
+        if (cause != null) {
+          cause.printStackTrace();
+        }
+        return FallbackError.defaultErrorJson(cause);
+      }
+      
+    };
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFeignClient.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFeignClient.java
new file mode 100644
index 0000000..7c25a01
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/biz/v1/admin/AdminBizRemoteFeignClient.java
@@ -0,0 +1,51 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.biz.v1.admin;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.biz.Biz;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.biz.configuration.BizFeignClientConfiguration;
+
+@FeignClient(
+    configuration = {BizFeignClientConfiguration.class},
+    name = "biz-admin-biz-remote-feign-client",
+    url = "${sw-backend-biz-api.uri}/v1/admin/biz",
+    fallbackFactory = AdminBizRemoteFallbackFactory.class
+)
+public interface AdminBizRemoteFeignClient {
+  
+  @RequestMapping(method = RequestMethod.GET)
+  JSONObject query(
+      @RequestParam(name = "loadAll") boolean loadAll,
+      @RequestParam(name = "pageIndex") int pageIndex,
+      @RequestParam(name = "pageSize") int pageSize
+      
+  );
+  
+  @RequestMapping(method = RequestMethod.GET, path = "/{id}")
+  JSONObject load(
+      @PathVariable(name = "id") String id
+  );
+
+  @RequestMapping(method = RequestMethod.POST)
+  JSONObject create(
+      @RequestBody Biz biz
+  );
+
+  @RequestMapping(method = RequestMethod.PUT, path = "/{id}")
+  JSONObject update(
+      @PathVariable(name = "id") String id,
+      @RequestBody Biz biz
+  );
+  
+  @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
+  JSONObject delete(
+      @PathVariable(name = "id") String id
+  );
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/exception/FallbackError.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/exception/FallbackError.java
new file mode 100644
index 0000000..14f8326
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/remote/exception/FallbackError.java
@@ -0,0 +1,21 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.remote.exception;
+
+import com.alibaba.fastjson.JSONObject;
+
+public class FallbackError {
+  
+  private FallbackError() {
+    
+  }
+  
+  public static JSONObject defaultErrorJson(Throwable cause) {
+    JSONObject error = new JSONObject();
+    
+    error.put("code", -1);
+    error.put("message", cause.getMessage());
+    error.put("error", cause.getMessage());
+    
+    return error;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/.gitkeep b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/.gitkeep
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/base/AuthnService.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/base/AuthnService.java
new file mode 100644
index 0000000..8f6d9df
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/base/AuthnService.java
@@ -0,0 +1,202 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.service.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Account;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Application;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Permission;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.PermissionRoleSet;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.ResourceRoleSet;
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.base.Role;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.base.v1.authn.AuthnRemoteFeignClient;
+
+@Slf4j
+@Service
+public class AuthnService {
+  
+  @Autowired
+  private AuthnRemoteFeignClient authnRemote;
+  
+  public Account account(String username) {
+    
+    JSONObject jsonObject = authnRemote.account(username);
+    if (jsonObject == null) {
+      return null;
+    }
+    
+    if (jsonObject.getIntValue("code") == 0) {
+      JSONObject data = jsonObject.getJSONObject("data");
+      
+      return data.toJavaObject(Account.class);
+    }
+    
+    return null;
+  }
+
+  public List<Role> roles(String username) {
+    
+    JSONObject jsonObject = authnRemote.roles(username);
+    if (jsonObject == null) {
+      return null;
+    }
+    
+    if (jsonObject.getIntValue("code") == 0) {
+      JSONObject data = jsonObject.getJSONObject("data");
+      
+      return data.getJSONArray("roles").toJavaList(Role.class);
+    }
+    
+    return null;
+  }
+
+  public List<Permission> menus(String username, String applicationId) {
+    
+    JSONObject jsonObject = authnRemote.menus(username, applicationId);
+    if (jsonObject == null) {
+      return null;
+    }
+    
+    if (jsonObject.getIntValue("code") == 0) {
+      JSONObject data = jsonObject.getJSONObject("data");
+      
+      return data.getJSONArray("permissions").toJavaList(Permission.class);
+    }
+    
+    return null;
+  }
+
+  
+  public List<Application> applications() {
+    
+    try {
+      JSONObject jsonObject = authnRemote.applications();
+      if (jsonObject == null) {
+        return null;
+      }
+      log.debug("{}", jsonObject.toJSONString());
+      
+      if (jsonObject.containsKey("code") && jsonObject.getIntValue("code") == 0) {
+        JSONObject data = jsonObject.getJSONObject("data");
+        
+        return data.getJSONArray("applications").toJavaList(Application.class);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    
+    return null;
+  }
+  
+  public List<Role> roles() {
+    
+    try {
+      JSONObject jsonObject = authnRemote.roles();
+      if (jsonObject == null) {
+        return null;
+      }
+      log.debug("{}", jsonObject.toJSONString());
+      
+      if (jsonObject.containsKey("code") && jsonObject.getIntValue("code") == 0) {
+        JSONObject data = jsonObject.getJSONObject("data");
+        
+        return data.getJSONArray("roles").toJavaList(Role.class);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    
+    return null;
+  }
+
+  
+  
+  
+
+  public static volatile Map<String, List<PermissionRoleSet>> mapPermissionRoleSets = 
+      new HashMap<String, List<PermissionRoleSet>>();
+  
+  public void putPermissionRoleSets(String applicationId, List<PermissionRoleSet> permissionRoleSets) {
+    AuthnService.mapPermissionRoleSets.put(applicationId, permissionRoleSets);
+  }
+  
+  public List<PermissionRoleSet> getPermissionRoleSets(String applicationId) {
+    if (StringUtils.isNotEmpty(applicationId)) {
+      return AuthnService.mapPermissionRoleSets.get(applicationId);
+    }
+    
+    List<PermissionRoleSet> allPermissionRoleSets = new ArrayList<>();
+    for (List<PermissionRoleSet> permissionRoleSets : AuthnService.mapPermissionRoleSets.values()) {
+      allPermissionRoleSets.addAll(permissionRoleSets);
+    }
+    
+    return allPermissionRoleSets;
+  }
+
+  public void loadPermissionRoleSets() {
+    
+    List<Application> applications = applications();
+    if (applications != null) {
+      for (Application application : applications) {
+        String applicationId = application.getId();
+        List<PermissionRoleSet> permissionRoleSets = this.permissionRoleSets(applicationId);
+        if (permissionRoleSets != null) {
+          this.putPermissionRoleSets(applicationId, permissionRoleSets);
+        }
+      }
+    }
+  }
+  
+  
+  public List<PermissionRoleSet> permissionRoleSets(String applicationId) {
+    
+    try {
+      JSONObject jsonObject = authnRemote.permissionRoleSets(applicationId);
+      if (jsonObject == null) {
+        return null;
+      }
+      log.debug("{}", jsonObject.toJSONString());
+      
+      if (jsonObject.containsKey("code") && jsonObject.getIntValue("code") == 0) {
+        JSONObject data = jsonObject.getJSONObject("data");
+        
+        return data.getJSONArray("permissionRoleSets").toJavaList(PermissionRoleSet.class);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    
+    return null;
+  }
+
+  public List<ResourceRoleSet> resourceRoleSets() {
+    
+    try {
+      JSONObject jsonObject = authnRemote.resourceRoleSets(null);
+      if (jsonObject == null) {
+        return null;
+      }
+      log.debug("{}", jsonObject.toJSONString());
+      
+      if (jsonObject.containsKey("code") && jsonObject.getIntValue("code") == 0) {
+        JSONObject data = jsonObject.getJSONObject("data");
+        
+        return data.getJSONArray("resourceRoleSets").toJavaList(ResourceRoleSet.class);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    
+    return null;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/biz/BizService.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/biz/BizService.java
new file mode 100644
index 0000000..0fa9bdf
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/service/biz/BizService.java
@@ -0,0 +1,32 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.service.biz;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.api.v1.remote.biz.v1.admin.AdminBizRemoteFeignClient;
+import com.supwisdom.institute.backend.admin.bff.api.v1.vo.biz.response.data.BizQueryResponseData;
+
+@Service
+public class BizService {
+  
+  @Autowired
+  private AdminBizRemoteFeignClient bizRemote;
+  
+  public BizQueryResponseData query(boolean loadAll, int pageIndex, int pageSize) {
+    
+    JSONObject jsonObject = bizRemote.query(loadAll, pageIndex, pageSize);
+    if (jsonObject == null) {
+      return null;
+    }
+    
+    if (jsonObject.getIntValue("code") == 0) {
+      JSONObject data = jsonObject.getJSONObject("data");
+      
+      return data.toJavaObject(BizQueryResponseData.class);
+    }
+    
+    return null;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/.gitkeep b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/.gitkeep
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/biz/response/data/BizQueryResponseData.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/biz/response/data/BizQueryResponseData.java
new file mode 100644
index 0000000..8b3891b
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/biz/response/data/BizQueryResponseData.java
@@ -0,0 +1,45 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.vo.biz.response.data;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.biz.Biz;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiQueryResponseData;
+
+public class BizQueryResponseData implements IApiQueryResponseData<Biz> {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -380945463584664943L;
+
+  @Getter
+  private boolean loadAll;
+  @Getter
+  private int pageIndex;
+  @Getter
+  private int pageSize;
+  @Getter
+  private Map<String, Object> mapBean;
+  @Getter
+  private Map<String, String> orderBy;
+  
+  @Getter
+  @Setter
+  private int pageCount;
+  @Getter
+  @Setter
+  private long recordCount;
+  
+  @Getter
+  @Setter
+  private int currentItemCount;
+  
+  @Getter
+  @Setter
+  private List<Biz> items;
+  
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/CurrentUserResponseData.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/CurrentUserResponseData.java
new file mode 100644
index 0000000..97443d3
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/CurrentUserResponseData.java
@@ -0,0 +1,23 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.vo.me.response.data;
+
+import org.springframework.beans.BeanUtils;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.me.CurrentUser;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiResponseData;
+
+public class CurrentUserResponseData extends CurrentUser implements IApiResponseData {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 2296310299015658064L;
+
+  public static CurrentUserResponseData of(CurrentUser currentUser) {
+    CurrentUserResponseData data = new CurrentUserResponseData();
+    
+    BeanUtils.copyProperties(currentUser, data);
+    
+    return data;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/GrantedMenusResponseData.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/GrantedMenusResponseData.java
new file mode 100644
index 0000000..2aacc52
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/me/response/data/GrantedMenusResponseData.java
@@ -0,0 +1,30 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.vo.me.response.data;
+
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.me.GrantedMenu;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiResponseData;
+
+public class GrantedMenusResponseData implements IApiResponseData {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -7495122676647463043L;
+  
+  @Getter
+  @Setter
+  private List<GrantedMenu> menus;
+
+  public static GrantedMenusResponseData of(List<GrantedMenu> grantedMenus) {
+    GrantedMenusResponseData data = new GrantedMenusResponseData();
+    
+    data.setMenus(grantedMenus);
+    
+    return data;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/MenusResponseData.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/MenusResponseData.java
new file mode 100644
index 0000000..6beabd2
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/MenusResponseData.java
@@ -0,0 +1,30 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.vo.open.response.data;
+
+import java.util.List;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.open.Menu;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiResponseData;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class MenusResponseData implements IApiResponseData {
+  
+  /**
+   * 
+   */
+  private static final long serialVersionUID = -3516729316884770800L;
+
+  @Getter
+  @Setter
+  private List<Menu> menus;
+
+  public static MenusResponseData of(List<Menu> menus) {
+    MenusResponseData data = new MenusResponseData();
+    
+    data.setMenus(menus);
+    
+    return data;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/OpenSyncRolesResponseData.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/OpenSyncRolesResponseData.java
new file mode 100644
index 0000000..69453b6
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/api/v1/vo/open/response/data/OpenSyncRolesResponseData.java
@@ -0,0 +1,35 @@
+package com.supwisdom.institute.backend.admin.bff.api.v1.vo.open.response.data;
+
+import java.util.List;
+
+import com.supwisdom.institute.backend.admin.bff.api.v1.model.open.SyncRoleModel;
+import com.supwisdom.institute.backend.common.framework.vo.response.data.IApiResponseData;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class OpenSyncRolesResponseData implements IApiResponseData {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 2739730369123803327L;
+  
+  @Getter
+  @Setter
+  private String applicationId;
+
+  @Getter
+  @Setter
+  private List<SyncRoleModel> roles;
+
+  public static OpenSyncRolesResponseData of(String applicationId, List<SyncRoleModel> roles) {
+    OpenSyncRolesResponseData data = new OpenSyncRolesResponseData();
+    
+    data.setApplicationId(applicationId);
+    data.setRoles(roles);
+    
+    return data;
+  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java
new file mode 100644
index 0000000..191e1e8
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java
@@ -0,0 +1,77 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * feign请求参数转化
+ * @author fengpy
+ */
+//@Configuration
+public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    public FeignBasicAuthRequestInterceptor() {}
+
+    @Override
+    public void apply(RequestTemplate template) {
+        ///**get-pojo贯穿*/
+        if (template.method().equals("GET") && template.request().body() != null) {
+            try {
+                JsonNode jsonNode = objectMapper.readTree(template.request().body());
+                //template.body(null);
+                Map<String, Collection<String>> queries = new HashMap<>();
+                //feign 不支持 GET 方法传 POJO, json body转query
+                buildQuery(jsonNode, "", queries);
+                template.queries(queries);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //处理 get-pojo贯穿
+    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
+        if (!jsonNode.isContainerNode()) { //叶子节点
+            if (jsonNode.isNull()) {
+                return;
+            }
+            Collection<String> values = queries.get(path);
+            if (null == values) {
+                values = new ArrayList<>();
+                queries.put(path, values);
+            }
+            values.add(jsonNode.asText());
+            return;
+        }
+        if (jsonNode.isArray()) { //数组节点
+            Iterator<JsonNode> it = jsonNode.elements();
+            while (it.hasNext()) {
+                buildQuery(it.next(), path, queries);
+            }
+        } else {
+            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
+            while (it.hasNext()) {
+                Map.Entry<String, JsonNode> entry = it.next();
+                if (StringUtils.hasText(path)) {
+                    if ("mapBean".equals(path)||"orderBy".equals(path)||"sequence".equals(path)) {
+                        buildQuery(entry.getValue(), path + "[" + entry.getKey() + "]", queries);
+                    } else {
+                        buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
+                    }
+                } else { //根节点
+                    buildQuery(entry.getValue(), entry.getKey(), queries);
+                }
+            }
+        }
+    }
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/Swagger2Config.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/Swagger2Config.java
new file mode 100644
index 0000000..5a1022a
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/Swagger2Config.java
@@ -0,0 +1,132 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.AuthorizationScopeBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.service.AuthorizationScope;
+import springfox.documentation.service.BasicAuth;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.SecurityReference;
+import springfox.documentation.service.SecurityScheme;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger.web.UiConfiguration;
+import springfox.documentation.swagger.web.UiConfigurationBuilder;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+import static com.google.common.collect.Lists.*;
+
+@Configuration
+@EnableSwagger2
+public class Swagger2Config {
+
+  @Value("${swagger2.apis.basePackage:com.supwisdom.institute}")
+  private String basePackage;
+
+  @Bean
+  public Docket createRestApi() {
+    return new Docket(DocumentationType.SWAGGER_2)
+        .securitySchemes(securitySchemes())
+        .securityContexts(securityContexts())
+        .apiInfo(apiInfo())
+        .select()
+        .apis(RequestHandlerSelectors.basePackage(basePackage))
+        .paths(PathSelectors.any())
+        .build()
+    ;
+  }
+
+  private ApiInfo apiInfo() {
+    Contact contact = new Contact("Backend Admin BFF", "https://sw-backend-api.supwisdom.com/swagger-ui.html", ""); // name, url, email
+    return new ApiInfoBuilder()
+        .title("Backend Admin BFF APIs")
+        .description("管理后台 - 后端接口<br /><br />"
+            + "X-FORWARD-USER(测试用):<br /><br />"
+            + "明文:{\"attributes\":{\"accountId\":\"1\"},\"roles\":[\"ROLE_ADMIN\",\"administrator\",\"user\"],\"username\":\"swadmin\"}<br /><br />"
+            + "Base64:eyJhdHRyaWJ1dGVzIjp7ImFjY291bnRJZCI6IjEifSwicm9sZXMiOlsiUk9MRV9BRE1JTiIsImFkbWluaXN0cmF0b3IiLCJ1c2VyIl0sInVzZXJuYW1lIjoic3dhZG1pbiJ9<br /><br />"
+            + "使用 Base64字符串 进行 Authorize,然后进行接口测试<br /><br />"
+            + "若需要其他帐号,请自行拼接明文,再进行 Base64 编码<br /><br />"
+            + ""
+        )
+        .termsOfServiceUrl("http://www.supwisdom.com/")
+        .contact(contact)
+        .version("1.0")
+        .build();
+  }
+  
+  private List<SecurityScheme> securitySchemes() {
+    //return newArrayList(new BasicAuth("sample"));
+    return newArrayList(
+        //new BasicAuth("Basic"),
+        //new ApiKey("JWTToken", "Authorization", "header"), 
+        new ApiKey("SimpleUserTransmit", "X-FORWARD-USER", "header"));
+  }
+  
+  private List<SecurityContext> securityContexts() {
+
+    List<SecurityReference> globalSecurityReference = newArrayList(
+        new SecurityReference("SimpleUserTransmit", new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")}));
+    
+//    AuthorizationScope[] authScopes = new AuthorizationScope[1];
+//    authScopes[0] = new AuthorizationScopeBuilder()
+//            .scope("read")
+//            .description("read access")
+//            .build();
+//    SecurityReference securityReference = SecurityReference.builder()
+//            .reference("sample")
+//            .scopes(authScopes)
+//            .build();
+
+    return newArrayList(
+        SecurityContext.builder()
+          .securityReferences(newArrayList(globalSecurityReference))
+          .build());
+  }
+
+  @Bean
+  public UiConfiguration uiConfig() {
+    
+    return UiConfigurationBuilder.builder().build();
+    
+//    return new UiConfiguration(null, // url
+//        "none", // docExpansion => none | list
+//        "alpha", // apiSorter => alpha
+//        "schema", // defaultModelRendering => schema
+//        UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS,
+//        false, // enableJsonEditor => true || false
+//        true, // showRequestHeaders => true | false
+//        60000L); // requestTimeout => in milliseconds, defaults to null
+//    // (uses jquery xh timeout)
+  }
+  
+  
+//  @Bean
+//  public SecurityConfiguration oauth2() {
+//      return SecurityConfigurationBuilder.builder()
+//          .clientId("common")
+//          .clientSecret("secret")
+//          .scopeSeparator(" ")
+//          .useBasicAuthenticationWithAccessCodeGrant(true)
+//          .build();
+//  }
+//  
+//  @Bean
+//  public SecurityConfiguration basic() {
+//      return SecurityConfigurationBuilder.builder()
+//          .clientId("common")
+//          .clientSecret("secret")
+//          .scopeSeparator(" ")
+//          .useBasicAuthenticationWithAccessCodeGrant(true)
+//          .build();
+//  }
+
+}
diff --git a/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/CurrentUserUtil.java b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/CurrentUserUtil.java
new file mode 100644
index 0000000..b97e5ae
--- /dev/null
+++ b/admin-bff/bff/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/CurrentUserUtil.java
@@ -0,0 +1,26 @@
+package com.supwisdom.institute.backend.admin.bff.utils;
+
+import com.supwisdom.institute.backend.common.core.transmit.user.User;
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+public class CurrentUserUtil {
+  
+  public static User currentUser() {
+    User user = UserContext.getUser();
+    
+    if (user == null) {
+      throw new RuntimeException("current user is null");
+    }
+    
+    return user;
+  }
+  
+  public static String currentUsername() {
+    return currentUser().getUsername();
+  }
+
+  public static String currentUserAccountId() {
+    return String.valueOf(currentUser().getAttributes().get("accountId"));
+  }
+
+}
diff --git a/admin-bff/bff/src/main/resources/application-docker.yml b/admin-bff/bff/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..81e78c9
--- /dev/null
+++ b/admin-bff/bff/src/main/resources/application-docker.yml
@@ -0,0 +1,74 @@
+server:
+  port: ${SERVER_PORT:8443}
+  ssl:
+    enabled: ${SSL_ENABLED:true}
+    clientAuth: NEED
+    key-store: ${SSL_KEYSTORE_FILE:file:/certs/server/server.keystore}
+    key-store-password: ${SSL_KEYSTORE_PASSWORD:}
+    trust-store: ${SSL_TRUSTSTORE_FILE:file:/certs/server/server.truststore}
+    trust-store-password: ${SSL_TRUSTSTORE_PASSWORD:}
+  tomcat: 
+    accesslog: 
+      enabled: ${TOMCAT_ACCESSLOG_ENABLED:false}
+      buffered: ${TOMCAT_ACCESSLOG_BUFFERED:true}
+      directory: ${TOMCAT_ACCESSLOG_DIR:log}
+      prefix: ${TOMCAT_ACCESSLOG_PREFIX:sa-api-accesslog}
+      suffix: ${TOMCAT_ACCESSLOG_SUFFIX:.log}
+      file-date-format: ${TOMCAT_ACCESSLOG_FILE_DATE_FORMAT:.yyyy-MM-dd}
+      rotate: ${TOMCAT_ACCESSLOG_ROTATE:true}
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: INFO
+
+
+spring:
+  jackson:
+    time-zone: ${JACKSON_TIME_ZONE:Asia/Shanghai}
+
+
+##
+# online-doc
+#
+infras.online-doc.enabled: ${INFRAS_ONLINE_DOC_ENABLED:false}
+infras.online-doc.md-docs.staitc.path: ${INFRAS_ONLINE_DOC_MD_DOCS_STATIC_PATH:/doc/}
+infras.online-doc.api-docs.staitc.path: ${INFRAS_ONLINE_DOC_API_DOCS_STATIC_PATH:/api-docs/}
+
+
+##
+# server url for feign
+#
+sw-backend-base-api: 
+  uri: ${SW_BACKEND_BASE_API_URI:https://sw-backend-admin-sa}
+  client-auth:
+    enabled: ${SW_BACKEND_BASE_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${SW_BACKEND_BASE_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${SW_BACKEND_BASE_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
+
+sw-backend-system-api: 
+  uri: ${SW_BACKEND_SYSTEM_API_URI:https://sw-backend-admin-sa}
+  client-auth:
+    enabled: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${SW_BACKEND_SYSTEM_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
+
+sw-backend-biz-api: 
+  uri: ${SW_BACKEND_BIZ_API_URI:https://sw-backend-biz-sa}
+  client-auth:
+    enabled: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${SW_BACKEND_BIZ_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
diff --git a/admin-bff/bff/src/main/resources/application.yml b/admin-bff/bff/src/main/resources/application.yml
new file mode 100644
index 0000000..8ad7215
--- /dev/null
+++ b/admin-bff/bff/src/main/resources/application.yml
@@ -0,0 +1,68 @@
+server:
+  port: 8081
+  ssl:
+    enabled: false
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: DEBUG
+#    org.springframework.web: INFO
+#    org.springframework.cloud.openfeign: INFO
+
+
+swagger2.apis.basePackage: com.supwisdom.institute
+
+
+spring:
+  jackson:
+    time-zone: Asia/Shanghai
+
+
+feign:
+  client:
+    config:
+      default:
+        #errorDecoder: com.supwisdom.leaveschool.common.config.BaseExceptionErrorDecoder
+        connectTimeout: 12000
+        readTimeout: 12000
+        loggerLevel: full
+  hystrix:
+    enabled: true
+  httpclient:
+    enabled: true
+
+hystrix:
+  command:
+    default:
+      execution:
+        timeout:
+          enabled: true
+        isolation:
+          thread:
+            timeoutInMilliseconds: 12000
+
+
+##
+# infras.online-doc
+#
+infras.online-doc.enabled: true
+infras.online-doc.md-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/doc/
+infras.online-doc.api-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/api-docs/
+
+
+##
+# server url for feign
+#
+sw-backend-base-api:
+  uri: http://localhost:8082
+
+sw-backend-system-api: 
+  uri: http://localhost:8082
+
+sw-backend-biz-api: 
+  uri: http://localhost:8082
diff --git a/admin-bff/bff/src/main/resources/bootstrap.yml b/admin-bff/bff/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..2df1be7
--- /dev/null
+++ b/admin-bff/bff/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+  application:
+    name: sw-backend-admin-bff