MaxKey преди 3 години
родител
ревизия
3e080d568f
променени са 49 файла, в които са добавени 487 реда и са изтрити 788 реда
  1. 2 12
      maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaEndpoint.java
  2. 24 0
      maxkey-common/src/main/java/org/maxkey/crypto/Base64Utils.java
  3. 2 3
      maxkey-core/src/main/java/org/maxkey/entity/UserInfo.java
  4. 3 4
      maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java
  5. 0 121
      maxkey-core/src/main/java/org/maxkey/web/image/AbstractImageEndpoint.java
  6. 0 57
      maxkey-core/src/main/java/org/maxkey/web/image/ImageEndpoint.java
  7. 0 57
      maxkey-core/src/main/java/org/maxkey/web/tag/CurrUrlTagDirective.java
  8. 0 65
      maxkey-core/src/main/java/org/maxkey/web/tag/DateTagDirective.java
  9. 0 48
      maxkey-core/src/main/java/org/maxkey/web/tag/GenIdTagDirective.java
  10. 0 55
      maxkey-core/src/main/java/org/maxkey/web/tag/ParameterTagDirective.java
  11. 0 67
      maxkey-core/src/main/java/org/maxkey/web/tag/PathVarTagDirective.java
  12. 0 66
      maxkey-core/src/main/java/org/maxkey/web/tag/RedirectTagDirective.java
  13. 0 86
      maxkey-core/src/main/java/org/maxkey/web/tag/StaticTagDirective.java
  14. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/app.module.ts
  15. 5 5
      maxkey-web-frontend/maxkey-web-app/src/app/core/startup/startup.service.ts
  16. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/global-config.module.ts
  17. 6 5
      maxkey-web-frontend/maxkey-web-app/src/app/layout/basic/basic.component.ts
  18. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/layout/layout.module.ts
  19. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/layout/passport/passport.component.ts
  20. 42 0
      maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/authz-mgt.component.ts
  21. 9 4
      maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/authz.module.ts
  22. 6 5
      maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/credential/credential.component.ts
  23. 106 0
      maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.html
  24. 0 0
      maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.less
  25. 25 0
      maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.spec.ts
  26. 79 0
      maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.ts
  27. 3 1
      maxkey-web-frontend/maxkey-web-app/src/app/routes/config/config.module.ts
  28. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/dashboard.module.ts
  29. 1 1
      maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/home/home.component.html
  30. 26 7
      maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/home/home.component.ts
  31. 4 5
      maxkey-web-frontend/maxkey-web-app/src/app/routes/delon/acl/acl.component.ts
  32. 7 8
      maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/callback.component.ts
  33. 18 19
      maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.ts
  34. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/routes/routes-routing.module.ts
  35. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/routes/routes.module.ts
  36. 26 5
      maxkey-web-frontend/maxkey-web-app/src/app/service/authn.service.ts
  37. 4 4
      maxkey-web-frontend/maxkey-web-app/src/app/shared/consts.ts
  38. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/shared/shared-delon.module.ts
  39. 3 4
      maxkey-web-frontend/maxkey-web-app/src/app/shared/shared-zorro.module.ts
  40. 4 4
      maxkey-web-frontend/maxkey-web-app/src/app/shared/shared.module.ts
  41. 6 4
      maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout-nav.component.html
  42. 14 4
      maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout-nav.component.ts
  43. 6 6
      maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout.module.ts
  44. 13 1
      maxkey-web-frontend/maxkey-web-app/src/assets/app-data.json
  45. 1 1
      maxkey-web-frontend/maxkey-web-app/src/assets/i18n/zh-CN.json
  46. 3 4
      maxkey-web-frontend/maxkey-web-app/src/environments/environment.ts
  47. 5 4
      maxkey-web-frontend/maxkey-web-app/src/style-icons-auto.ts
  48. 1 3
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/AppListController.java
  49. 9 11
      maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/OneTimePasswordController.java

+ 2 - 12
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaEndpoint.java

@@ -19,13 +19,9 @@ package org.maxkey.web.contorller;
 
 import com.google.code.kaptcha.Producer;
 import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.util.Base64;
-
-import javax.imageio.ImageIO;
-
 import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authn.jwt.AuthTokenService;
+import org.maxkey.crypto.Base64Utils;
 import org.maxkey.entity.Message;
 import org.maxkey.persistence.MomentaryService;
 import org.slf4j.Logger;
@@ -94,16 +90,10 @@ public class ImageCaptchaEndpoint {
             momentaryService.put("", kaptchaKey, kaptchaValue);
             // create the image with the text
             BufferedImage bufferedImage = captchaProducer.createImage(kaptchaText);
-            // write the data out
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-			ImageIO.write(bufferedImage, "png", stream);
-			
-			String b64Image = "data:image/png;base64," + 
-					Base64.getEncoder().encodeToString(stream.toByteArray());
+			String b64Image = Base64Utils.encodeImage(bufferedImage);
            
             _logger.trace("b64Image {}" , b64Image);
             
-            stream.close();
             return new Message<ImageCaptcha>(
             			new ImageCaptcha(state,b64Image)
             		).buildResponse();

+ 24 - 0
maxkey-common/src/main/java/org/maxkey/crypto/Base64Utils.java

@@ -17,9 +17,14 @@
 
 package org.maxkey.crypto;
 
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+
+import javax.imageio.ImageIO;
+
 import org.apache.commons.codec.binary.Base64;
 
 /**
@@ -56,6 +61,25 @@ public final class Base64Utils {
         return decoderBase64(cipher);
     }
 
+    public static String encodeImage(BufferedImage bufferedImage) {
+    	try {
+    		ByteArrayOutputStream stream = new ByteArrayOutputStream();
+			ImageIO.write(bufferedImage, "png", stream);
+			String b64Image = "data:image/png;base64," + 
+					java.util.Base64.getEncoder().encodeToString(stream.toByteArray());
+			stream.close();
+	        return b64Image;
+    	}catch (Exception e) {
+    		e.printStackTrace();
+    	}
+    	return "";
+    }
+    
+    public static String encodeImage(byte[] byteImage) {
+    	return "data:image/png;base64," + 
+    			java.util.Base64.getEncoder().encodeToString(byteImage);
+    }
+    
     /**
      * encode file to base64 Code String.
      * 

+ 2 - 3
maxkey-core/src/main/java/org/maxkey/entity/UserInfo.java

@@ -18,7 +18,6 @@
 package org.maxkey.entity;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import java.util.Base64;
 import java.util.HashMap;
 import java.util.List;
 
@@ -29,6 +28,7 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.Table;
 import org.apache.mybatis.jpa.persistence.JpaBaseEntity;
+import org.maxkey.crypto.Base64Utils;
 import org.maxkey.util.StringUtils;
 
 /**
@@ -421,8 +421,7 @@ public class UserInfo extends JpaBaseEntity {
 
 	public void transPictureBase64() {
 		if(picture != null) {
-			this.pictureBase64 = "data:image/png;base64," + 
-					Base64.getEncoder().encodeToString(picture);
+			this.pictureBase64 = Base64Utils.encodeImage(picture);
 		}
 	}
 	

+ 3 - 4
maxkey-core/src/main/java/org/maxkey/entity/apps/Apps.java

@@ -1,5 +1,5 @@
 /*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
 package org.maxkey.entity.apps;
 
 import java.io.Serializable;
-import java.util.Base64;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -29,6 +28,7 @@ import javax.persistence.Table;
 
 import org.apache.mybatis.jpa.persistence.JpaBaseEntity;
 import org.maxkey.constants.ConstsBoolean;
+import org.maxkey.crypto.Base64Utils;
 
 @Entity
 @Table(name = "MXK_APPS")
@@ -292,8 +292,7 @@ public class Apps extends JpaBaseEntity implements Serializable {
 	
 	public void transIconBase64() {
 		if(icon !=null) {
-			this.iconBase64 = "data:image/png;base64," + 
-					Base64.getEncoder().encodeToString(icon);
+			this.iconBase64 = Base64Utils.encodeImage(icon);
 		}
 	}
 

+ 0 - 121
maxkey-core/src/main/java/org/maxkey/web/image/AbstractImageEndpoint.java

@@ -1,121 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.image;
-
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import javax.imageio.ImageIO;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.maxkey.configuration.ApplicationConfig;
-import org.maxkey.constants.ContentType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-
-
-/**
- * AbstractImageEndpoint  Producer Image .
- * @author Crystal.Sea
- *
- */
-
-public class AbstractImageEndpoint {
-    private static final Logger _logger = LoggerFactory.getLogger(AbstractImageEndpoint.class);
-
-    @Autowired
-    @Qualifier("applicationConfig")
-    protected ApplicationConfig applicationConfig;
-
-    /**
-     * producerImage.
-     * @param request HttpServletRequest
-     * @param response HttpServletResponse
-     * @param bufferedImage BufferedImage
-     * @throws IOException error
-     */
-    public static void producerImage(HttpServletRequest request, 
-                              HttpServletResponse response,
-                              BufferedImage bufferedImage) throws IOException {
-        // Set to expire far in the past.
-        response.setDateHeader("Expires", 0);
-        // Set standard HTTP/1.1 no-cache headers.
-        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
-        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
-        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
-        // Set standard HTTP/1.0 no-cache header.
-        response.setHeader("Pragma", "no-cache");
-        // return a jpeg/gif
-        response.setContentType(ContentType.IMAGE_GIF);
-        _logger.trace("create the image");
-        // create the image
-        if (bufferedImage != null) {
-            ServletOutputStream out = response.getOutputStream();
-            // write the data out
-            ImageIO.write(bufferedImage, "gif", out);
-            try {
-                out.flush();
-            } finally {
-                out.close();
-            }
-        }
-    }
-    
-    /**
-     * byte2BufferedImage.
-     * @param imageByte bytes
-     * @return
-     */
-    public static BufferedImage byte2BufferedImage(byte[] imageByte) {
-        try {
-            InputStream in = new ByteArrayInputStream(imageByte);
-            BufferedImage bufferedImage = ImageIO.read(in);
-            return bufferedImage;
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    /**
-     * bufferedImage2Byte.
-     * @param bufferedImage  BufferedImage
-     * @return
-     */
-    public static byte[] bufferedImage2Byte(BufferedImage bufferedImage) {
-        try {
-            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-            ImageIO.write(bufferedImage, "gif", byteArrayOutputStream);
-            return byteArrayOutputStream.toByteArray();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-
-    public void setApplicationConfig(ApplicationConfig applicationConfig) {
-        this.applicationConfig = applicationConfig;
-    }
-
-}

+ 0 - 57
maxkey-core/src/main/java/org/maxkey/web/image/ImageEndpoint.java

@@ -1,57 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.image;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-
-/**
- * ImageEndpoint  Producer Image and captcha.
- * @author Crystal.Sea
- *
- */
-@Controller
-public class ImageEndpoint extends AbstractImageEndpoint {
-    private static final Logger _logger = LoggerFactory.getLogger(ImageEndpoint.class);
-
-    /**
-     * Session Image Producer.
-     * 
-     * @param request HttpServletRequest
-     * @param response HttpServletResponse
-     */
-
-    @RequestMapping("/image/{id}")
-    public void imageHandleRequest(HttpServletRequest request, HttpServletResponse response,
-            @PathVariable("id") String id) {
-        try {
-            // get session image bytes
-            byte[] image = (byte[]) request.getSession().getAttribute(id);
-            producerImage(request,response,byte2BufferedImage(image));
-        } catch (Exception e) {
-            _logger.error("captcha Producer Error " + e.getMessage());
-        }   
-    }
-
-}

+ 0 - 57
maxkey-core/src/main/java/org/maxkey/web/tag/CurrUrlTagDirective.java

@@ -1,57 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
- *   获取当前页面地址标签
- *   <@currUrl/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("currUrl")
-public class CurrUrlTagDirective implements TemplateDirectiveModel {
-	@Autowired
-    private HttpServletRequest request;
-
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-		//String url = params.get(URL).toString();
-
-		String  currUrl=request.getRequestURI();
-		
-		env.getOut().append(currUrl);
-		
-
-	}
-
-}

+ 0 - 65
maxkey-core/src/main/java/org/maxkey/web/tag/DateTagDirective.java

@@ -1,65 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.maxkey.util.DateUtils;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *   获取应用上下文标签
- *   <@date format="" value=""></@date>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("date")
-public class DateTagDirective implements TemplateDirectiveModel {
-
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-		String dateValue = params.get("value").toString();
-		String format = params.get("format").toString();
-		String dateString="";
-		if(dateValue==null) {
-			if(format==null) {
-				dateString=DateUtils.getCurrentDateAsString(DateUtils.FORMAT_DATE_YYYY_MM_DD);
-			}else {
-				dateString=DateUtils.getCurrentDateAsString(format);
-			}
-		}else {
-			if(format==null) {
-				dateString=DateUtils.format(DateUtils.tryParse(dateValue),DateUtils.FORMAT_DATE_YYYY_MM_DD);
-			}else {
-				dateString=DateUtils.format(DateUtils.tryParse(dateValue),format);
-			}
-		}
-		
-		env.getOut().append(dateString);
-		
-	}
-
-}

+ 0 - 48
maxkey-core/src/main/java/org/maxkey/web/tag/GenIdTagDirective.java

@@ -1,48 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.UUID;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *   获取应用上下文标签
- *   <@genId/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("genId")
-public class GenIdTagDirective implements TemplateDirectiveModel {
-	
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-		env.getOut().append(UUID.randomUUID().toString().toLowerCase());
-		
-
-	}
-
-}

+ 0 - 55
maxkey-core/src/main/java/org/maxkey/web/tag/ParameterTagDirective.java

@@ -1,55 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *   获取应用上下文标签
- *   <@parameter/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("parameter")
-public class ParameterTagDirective implements TemplateDirectiveModel {
-	@Autowired
-    private HttpServletRequest request;
-	
-	private String name;
-	
-
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-			name=params.get("name").toString();
-			env.getOut().append(request.getParameter(name));
-	}
-
-}

+ 0 - 67
maxkey-core/src/main/java/org/maxkey/web/tag/PathVarTagDirective.java

@@ -1,67 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *   获取应用上下文标签
- *   <@pathVar/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("pathVar")
-public class PathVarTagDirective implements TemplateDirectiveModel {
-	@Autowired
-    private HttpServletRequest request;
-	
-	private int index;
-	String pathVariable;
-
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-		
-		index=Integer.parseInt(params.get("index").toString());
-		String[] pathVariables=request.getAttribute(org.springframework.web.util.WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE).toString().split("/");
-		
-		if(pathVariables==null){
-			pathVariables=request.getRequestURI().split("/");
-		}
-		
-		if(index==0){
-			pathVariable=pathVariables[pathVariables.length-1];
-		}else{
-			pathVariable=pathVariables[index+1];
-		}
-			env.getOut().append(request.getParameter(pathVariable));
-	}
-
-}

+ 0 - 66
maxkey-core/src/main/java/org/maxkey/web/tag/RedirectTagDirective.java

@@ -1,66 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *   获取应用上下文标签
- *   <@locale/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("redirect")
-public class RedirectTagDirective implements TemplateDirectiveModel {
-	@Autowired
-    private HttpServletRequest request;
-	private HttpServletResponse response;
-	
-	private String basePath = null;
-	
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-			String location=params.get("url").toString();
-
-			basePath = request.getScheme()+"://"+request.getServerName();
-			int port=request.getServerPort();
-			//Ignore 443 or 80 port
-			if((port==443 && request.getScheme().equalsIgnoreCase("https"))
-					||(port==80 && request.getScheme().equalsIgnoreCase("http"))){
-			}else{
-				basePath	+=	":"+port;
-			}
-			basePath += request.getContextPath()+"";
-			
-			response.sendRedirect(basePath+"/"+location);
-	}
-
-}

+ 0 - 86
maxkey-core/src/main/java/org/maxkey/web/tag/StaticTagDirective.java

@@ -1,86 +0,0 @@
-/*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.maxkey.web.tag;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.Map;
-
-import freemarker.core.Environment;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-/**
-    *  静态变量读取
- *   <@static/>
- * @author Crystal.Sea
- *
- */
-
-@FreemarkerTag("static")
-public class StaticTagDirective implements TemplateDirectiveModel {
-	
-
-	@Override
-	@SuppressWarnings("rawtypes")
-	public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
-			throws TemplateException, IOException {
-		 
-	        // 获取字符串变量
-	        String[] c = params.get("name").toString().trim().split("@");
-	 
-	        StringBuffer sb = new StringBuffer();
-	        try {
-	            if(null == c || c.length < 2) {
-	                throw new TemplateException("至少应该包含一个@符。", env);
-	            }
-	 
-	            Class<?> clazz = null;
-	            for(int i=0;i<c.length;i++) {
-	                sb.append(c[i]).append("@");
-	                if(i == 0) {
-	                    clazz = Class.forName(c[i]);
-	                } else if(i != c.length - 1) {
-	                    Class<?>[] clazzs = clazz.getDeclaredClasses();
-	                    boolean flag = false;
-	                    for(Class<?> clz : clazzs) {
-	                        if(clz.getSimpleName().equals(c[i])) {
-	                            clazz = clz;
-	                            flag = true;
-	                            break;
-	                        }
-	                    }
-	                    if(!flag) {
-	                        throw new TemplateException("内部类 " + sb.substring(0, sb.length() - 1) + " 未找到。", env);
-	                    }
-	                } else {
-	                    Field sp = clazz.getDeclaredField(c[i]);
-	                    env.getOut().write(sp.get(clazz).toString());
-	                }
-	            }
-	        } catch (ClassNotFoundException e) {
-	            throw new TemplateException("类 " + sb.substring(0, sb.length() - 1) + " 未找到。", e.getCause(), env);
-	        } catch (NoSuchFieldException e) {
-	            throw new TemplateException("属性 " + sb.substring(0, sb.length() - 1) + " 未找到。", e.getCause(), env);
-	        } catch (IllegalAccessException e) {
-	            throw new TemplateException("没权限访问 " + sb.substring(0, sb.length() - 1) + " 属性。", e.getCause(), env);
-	        }
-	}
-
-}

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/app.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 /* eslint-disable import/order */
 /* eslint-disable import/no-duplicates */

+ 5 - 5
maxkey-web-frontend/maxkey-web-app/src/app/core/startup/startup.service.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { HttpClient } from '@angular/common/http';
 import { Inject, Injectable } from '@angular/core';
@@ -66,7 +65,8 @@ export class StartupService {
         // 用户信息:包括姓名、头像、邮箱地址
         //this.settingService.setUser(appData.user);
         // ACL:设置权限为全量
-        this.aclService.setFull(true);
+        this.aclService.setFull(false);
+
         // 初始化菜单
         this.menuService.add(appData.menu);
         // 设置页面标题的后缀

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/global-config.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 /* eslint-disable import/order */
 import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';

+ 6 - 5
maxkey-web-frontend/maxkey-web-app/src/app/layout/basic/basic.component.ts

@@ -1,26 +1,27 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
+import { ACLService } from '@delon/acl';
 import { SettingsService, User } from '@delon/theme';
 import { environment } from '@env/environment';
 import { CONSTS } from 'src/app/shared/consts';
 
+import { AuthnService } from '../../service/authn.service';
 import { LayoutDefaultOptions } from '../../theme/layout-default';
 
 @Component({

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/layout/layout.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/layout/passport/passport.component.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Component, Inject, OnInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';

+ 42 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/authz-mgt.component.ts

@@ -0,0 +1,42 @@
+/*
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Inject, Optional, Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { ReuseTabService } from '@delon/abc/reuse-tab';
+import { SettingsService } from '@delon/theme';
+import { environment } from '@env/environment';
+
+import { AuthnService } from '../../service/authn.service';
+import { SocialsProviderService } from '../../service/socials-provider.service';
+
+@Component({
+  selector: 'app-callback',
+  template: ``
+})
+export class AuthzMgtComponent implements OnInit {
+  constructor() { }
+
+  ngOnInit(): void {
+    let baseUrl = '';
+    if (environment.api.baseUrl.endsWith('/')) {
+      baseUrl = environment.api.baseUrl.substring(0, environment.api.baseUrl.length - 1);
+    } else {
+      baseUrl = environment.api.baseUrl;
+    }
+    window.location.href = `${baseUrl}/authz/jwt/maxkey_mgt`;
+  }
+}

+ 9 - 4
maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/authz.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
@@ -21,6 +20,7 @@ import { RouterModule, Routes } from '@angular/router';
 import { SharedModule } from '@shared';
 
 import { LayoutBlankComponent } from '../../layout/blank/blank.component';
+import { AuthzMgtComponent } from './authz-mgt.component';
 import { CredentialComponent } from './credential/credential.component';
 import { Oauth2ApproveComponent } from './oauth2-approve/oauth2-approve.component';
 const routes: Routes = [
@@ -43,6 +43,11 @@ const routes: Routes = [
         path: 'oauth2approve',
         component: Oauth2ApproveComponent,
         data: { title: 'credential', titleI18n: 'app.login.login' }
+      },
+      {
+        path: 'mgt',
+        component: AuthzMgtComponent,
+        data: { title: 'mgt', titleI18n: 'app.login.login' }
       }
     ]
   }

+ 6 - 5
maxkey-web-frontend/maxkey-web-app/src/app/routes/authz/credential/credential.component.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, Inject, OnDestroy, Optional } from '@angular/core';
 import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
@@ -70,7 +69,9 @@ export class CredentialComponent implements OnInit {
       if (res.code == 0) {
         this.form.model.init(res.data);
         this.msg.success(`提交成功`);
-        window.location.href = `${environment.api.baseUrl}${this.redirect_uri}`;
+        if (this.redirect_uri) {
+          window.location.href = `${environment.api.baseUrl}${this.redirect_uri}`;
+        }
       } else {
         this.msg.success(`提交失败`);
       }

+ 106 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.html

@@ -0,0 +1,106 @@
+<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit()" se-container="1">
+  <nz-form-item style="display: none">
+    <nz-form-label [nzMd]="6" nzFor="id">id</nz-form-label>
+    <nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
+      <input [(ngModel)]="form.model.id" [ngModelOptions]="{ standalone: true }" nz-input name="id" id="id" value="id" />
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="displayName">{{ 'mxk.password.displayName' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not displayName!">
+      <input
+        nz-input
+        disabled="true"
+        [(ngModel)]="form.model.displayName"
+        [ngModelOptions]="{ standalone: true }"
+        name="displayName"
+        id="displayName"
+        value="0"
+      />
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="username">{{ 'mxk.accounts.username' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid username!">
+      <input
+        nz-input
+        disabled="true"
+        [(ngModel)]="form.model.username"
+        [ngModelOptions]="{ standalone: true }"
+        name="username"
+        id="username"
+      />
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="appName">{{ 'mxk.accounts.appName' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid appName!">
+      <input
+        nz-input
+        disabled="true"
+        [(ngModel)]="form.model.appName"
+        [ngModelOptions]="{ standalone: true }"
+        name="appName"
+        id="appName"
+      />
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="relatedUsername">{{ 'mxk.accounts.relatedUsername' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid relatedUsername!">
+      <input
+        nz-input
+        [(ngModel)]="form.model.relatedUsername"
+        [ngModelOptions]="{ standalone: true }"
+        name="relatedUsername"
+        id="relatedUsername"
+      />
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label nzRequired [nzSm]="6" [nzXs]="24" nzFor="relatedPassword">{{ 'mxk.accounts.relatedPassword' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid relatedPassword!">
+      <nz-input-group [nzSuffix]="suffixPasswordTemplate" style="width: 100%">
+        <input
+          [type]="passwordVisible ? 'text' : 'password'"
+          nz-input
+          placeholder="new password"
+          [(ngModel)]="form.model.relatedPassword"
+          [ngModelOptions]="{ standalone: true }"
+          name="relatedPassword"
+          id="relatedPassword"
+        />
+      </nz-input-group>
+      <ng-template #suffixPasswordTemplate>
+        <i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" (click)="passwordVisible = !passwordVisible"></i>
+      </ng-template>
+    </nz-form-control>
+  </nz-form-item>
+  <nz-form-item style="width: 100%">
+    <nz-form-label nzRequired [nzSm]="6" [nzXs]="24" nzFor="confirmPassword">{{ 'mxk.password.confirmPassword' | i18n }}</nz-form-label>
+    <nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid confirmPassword!">
+      <nz-input-group [nzSuffix]="suffixConfirmPasswordTemplate" style="width: 100%">
+        <input
+          [type]="confirmPasswordVisible ? 'text' : 'password'"
+          nz-input
+          placeholder="confirm password"
+          [(ngModel)]="form.model.confirmPassword"
+          [ngModelOptions]="{ standalone: true }"
+          name="confirmPassword"
+          id="confirmPassword"
+        />
+      </nz-input-group>
+      <ng-template #suffixConfirmPasswordTemplate>
+        <i
+          nz-icon
+          [nzType]="confirmPasswordVisible ? 'eye-invisible' : 'eye'"
+          (click)="confirmPasswordVisible = !confirmPasswordVisible"
+        ></i>
+      </ng-template>
+    </nz-form-control>
+  </nz-form-item>
+</form>
+<div *nzModalFooter>
+  <button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
+  <button nz-button nzType="primary" (click)="onSubmit()">{{ 'mxk.text.submit' | i18n }}</button>
+</div>

+ 0 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.less


+ 25 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.spec.ts

@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AccoutsComponent } from './accouts.component';
+
+describe('AccoutsComponent', () => {
+  let component: AccoutsComponent;
+  let fixture: ComponentFixture<AccoutsComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ AccoutsComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(AccoutsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 79 - 0
maxkey-web-frontend/maxkey-web-app/src/app/routes/config/accouts/accouts.component.ts

@@ -0,0 +1,79 @@
+import { Component, ChangeDetectorRef, OnInit, Input } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router, ActivatedRoute } from '@angular/router';
+import { environment } from '@env/environment';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
+
+import { Accounts } from '../../../entity/Accounts';
+import { AccountsService } from '../../../service/accounts.service';
+@Component({
+  selector: 'app-accouts',
+  templateUrl: './accouts.component.html',
+  styleUrls: ['./accouts.component.less']
+})
+export class AccoutsComponent implements OnInit {
+  @Input() appId?: String;
+
+  form: {
+    submitting: boolean;
+    model: Accounts;
+  } = {
+      submitting: false,
+      model: new Accounts()
+    };
+  redirect_uri: string = '';
+  formGroup: FormGroup = new FormGroup({});
+
+  confirmPasswordVisible = false;
+
+  passwordVisible = false;
+
+  constructor(
+    fb: FormBuilder,
+    private router: Router,
+    private route: ActivatedRoute,
+    private modalRef: NzModalRef,
+    private accountsService: AccountsService,
+    private msg: NzMessageService,
+    private cdr: ChangeDetectorRef
+  ) { }
+
+  ngOnInit(): void {
+    if (this.appId) {
+      this.accountsService.get(this.appId).subscribe(res => {
+        console.log(res.data);
+        this.form.model.init(res.data);
+        this.cdr.detectChanges();
+      });
+    }
+  }
+
+  onClose(e: MouseEvent): void {
+    e.preventDefault();
+    this.modalRef.destroy({ refresh: false });
+  }
+
+  onSubmit(): void {
+    this.form.submitting = true;
+    this.form.model.trans();
+    //if (this.formGroup.valid) {
+    this.accountsService.update(this.form.model).subscribe(res => {
+      if (res.code == 0) {
+        this.form.model.init(res.data);
+        this.msg.success(`提交成功`);
+        if (this.redirect_uri) {
+          window.location.href = `${environment.api.baseUrl}${this.redirect_uri}`;
+        }
+      } else {
+        this.msg.success(`提交失败`);
+      }
+    });
+    // } else {
+    //  this.formGroup.updateValueAndValidity({ onlySelf: true });
+    // this.msg.success(`提交失败`);
+    //}
+    this.form.submitting = false;
+    this.cdr.detectChanges();
+  }
+}

+ 3 - 1
maxkey-web-frontend/maxkey-web-app/src/app/routes/config/config.module.ts

@@ -33,6 +33,7 @@ import { ProfileComponent } from './profile/profile.component';
 import { SocialsAssociateComponent } from './socials-associate/socials-associate.component';
 import { SocialsProviderComponent } from './socials-provider/socials-provider.component';
 import { TimebasedComponent } from './timebased/timebased.component';
+import { AccoutsComponent } from './accouts/accouts.component';
 
 const routes: Routes = [
   {
@@ -62,7 +63,8 @@ const COMPONENTS = [ProfileComponent];
     TimebasedComponent,
     SocialsAssociateComponent,
     PasswordComponent,
-    ProfileComponent
+    ProfileComponent,
+    AccoutsComponent
   ],
   imports: [SharedModule, CommonModule, RouterModule.forChild(routes)],
   exports: [RouterModule]

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/dashboard.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { NgModule } from '@angular/core';
 import { CountDownModule } from '@delon/abc/count-down';

+ 1 - 1
maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/home/home.component.html

@@ -34,7 +34,7 @@
         </ng-template>-->
             <nz-card-meta [nzTitle]="item.title" [nzAvatar]="nzAvatar" *ngIf="item.protocol == 'Form_Based'">
               <ng-template #nzAvatar>
-                <i nz-icon nzType="setting" nzTheme="outline"></i>
+                <i nz-icon nzType="user-add" nzTheme="outline" (click)="setAccount(item.id)"> </i>
                 <!--<nz-avatar nzSize="small" [nzSrc]="item.iconBase64"></nz-avatar>-->
               </ng-template>
             </nz-card-meta>

+ 26 - 7
maxkey-web-frontend/maxkey-web-app/src/app/routes/dashboard/home/home.component.ts

@@ -1,30 +1,36 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Platform } from '@angular/cdk/platform';
 import { DOCUMENT } from '@angular/common';
-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit, Renderer2 } from '@angular/core';
+import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, Inject, OnInit, Renderer2 } from '@angular/core';
 import type { Chart } from '@antv/g2';
 import { OnboardingService } from '@delon/abc/onboarding';
+import { ACLService } from '@delon/acl';
 import { environment } from '@env/environment';
 import { format } from 'date-fns';
 import { NzSafeAny } from 'ng-zorro-antd/core/types';
+import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
+import { CONSTS } from 'src/app/shared/consts';
 
 import { AppListService } from '../../../service/appList.service';
+import { AuthnService } from '../../../service/authn.service';
+import { AccoutsComponent } from '../../config/accouts/accouts.component';
+
+import { Console } from 'console';
 
 @Component({
   selector: 'app-home',
@@ -47,6 +53,8 @@ export class HomeComponent implements OnInit {
   baseUrl: String = '';
 
   constructor(
+    private modal: NzModalService,
+    private viewContainerRef: ViewContainerRef,
     private appListService: AppListService,
     private cdr: ChangeDetectorRef,
     private obSrv: OnboardingService,
@@ -77,15 +85,26 @@ export class HomeComponent implements OnInit {
     }
     window.open(`${this.baseUrl}/authz/${appId}`);
   }
+  setAccount(appId: string): void {
+    const modal = this.modal.create({
+      nzContent: AccoutsComponent,
+      nzViewContainerRef: this.viewContainerRef,
+      nzComponentParams: {
+        appId: appId
+      },
+      nzWidth: 550
+      //nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
+    });
+  }
+
   ngOnInit(): void {
     if (environment.api.baseUrl.endsWith('/')) {
       this.baseUrl = environment.api.baseUrl.substring(0, environment.api.baseUrl.length - 1);
     } else {
       this.baseUrl = environment.api.baseUrl;
     }
-
     this.appListService.appList().subscribe(res => {
-      console.log(res.data);
+      //console.log(res.data);
       this.appList = res.data;
       this.cdr.detectChanges();
     });

+ 4 - 5
maxkey-web-frontend/maxkey-web-app/src/app/routes/delon/acl/acl.component.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Component } from '@angular/core';
 import { ACLService } from '@delon/acl';
@@ -36,7 +35,7 @@ export class ACLComponent {
     return this.aclSrv.data;
   }
 
-  constructor(private aclSrv: ACLService, private menuSrv: MenuService) {}
+  constructor(private aclSrv: ACLService, private menuSrv: MenuService) { }
 
   private reMenu(): void {
     this.menuSrv.resume();

+ 7 - 8
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/callback.component.ts

@@ -1,26 +1,25 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Inject, Optional, Component, OnInit } from '@angular/core';
 import { ActivatedRoute, Router } from '@angular/router';
 import { ReuseTabService } from '@delon/abc/reuse-tab';
 import { SettingsService } from '@delon/theme';
 
-import { AuthenticationService } from '../../service/authentication.service';
+import { AuthnService } from '../../service/authn.service';
 import { SocialsProviderService } from '../../service/socials-provider.service';
 
 @Component({
@@ -34,7 +33,7 @@ export class CallbackComponent implements OnInit {
     private router: Router,
     private socialsProviderService: SocialsProviderService,
     private settingsService: SettingsService,
-    private authenticationService: AuthenticationService,
+    private authnService: AuthnService,
     @Optional()
     @Inject(ReuseTabService)
     private reuseTabService: ReuseTabService,
@@ -49,9 +48,9 @@ export class CallbackComponent implements OnInit {
           // 清空路由复用信息
           this.reuseTabService.clear();
           // 设置用户Token信息
-          this.authenticationService.auth(res.data);
+          this.authnService.auth(res.data);
         }
-        this.authenticationService.navigate({});
+        this.authnService.navigate({});
       });
     } else {
       this.socialsProviderService.bind(this.provider, this.route.snapshot.queryParams).subscribe(res => {

+ 18 - 19
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit, OnDestroy, AfterViewInit, Optional } from '@angular/core';
 import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
@@ -27,7 +26,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzTabChangeEvent } from 'ng-zorro-antd/tabs';
 import { finalize } from 'rxjs/operators';
 
-import { AuthenticationService } from '../../../service/authentication.service';
+import { AuthnService } from '../../../service/authn.service';
 import { ImageCaptchaService } from '../../../service/image-captcha.service';
 import { SocialsProviderService } from '../../../service/socials-provider.service';
 import { CONSTS } from '../../../shared/consts';
@@ -65,7 +64,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
     fb: FormBuilder,
     private router: Router,
     private settingsService: SettingsService,
-    private authenticationService: AuthenticationService,
+    private authnService: AuthnService,
     private socialsProviderService: SocialsProviderService,
     private imageCaptchaService: ImageCaptchaService,
     @Optional()
@@ -88,7 +87,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
   ngOnInit(): void {
     //set redirect_uri , is BASE64URL
     if (this.route.snapshot.queryParams[CONSTS.REDIRECT_URI]) {
-      this.authenticationService.setRedirectUri(this.route.snapshot.queryParams[CONSTS.REDIRECT_URI]);
+      this.authnService.setRedirectUri(this.route.snapshot.queryParams[CONSTS.REDIRECT_URI]);
     }
 
     //congress login
@@ -97,8 +96,8 @@ export class UserLoginComponent implements OnInit, OnDestroy {
     }
 
     //init socials,state
-    this.authenticationService.clear();
-    this.authenticationService
+    this.authnService.clear();
+    this.authnService
       .get({ remember_me: localStorage.getItem(CONSTS.REMEMBER) })
       .pipe(
         finalize(() => {
@@ -118,8 +117,8 @@ export class UserLoginComponent implements OnInit, OnDestroy {
             // 清空路由复用信息
             this.reuseTabService.clear();
             // 设置用户Token信息
-            this.authenticationService.auth(res.data);
-            this.authenticationService.navigate({});
+            this.authnService.auth(res.data);
+            this.authnService.navigate({});
           } else {
             this.socials = res.data.socials;
             this.state = res.data.state;
@@ -136,7 +135,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
   }
 
   congressLogin(congress: string) {
-    this.authenticationService
+    this.authnService
       .congress({
         congress: congress
       })
@@ -154,8 +153,8 @@ export class UserLoginComponent implements OnInit, OnDestroy {
           // 清空路由复用信息
           this.reuseTabService.clear();
           // 设置用户Token信息
-          this.authenticationService.auth(res.data);
-          this.authenticationService.navigate({});
+          this.authnService.auth(res.data);
+          this.authnService.navigate({});
         }
       });
   }
@@ -199,7 +198,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
       this.mobile.updateValueAndValidity({ onlySelf: true });
       return;
     }
-    this.authenticationService.produceOtp({ mobile: this.mobile.value }).subscribe(res => {
+    this.authnService.produceOtp({ mobile: this.mobile.value }).subscribe(res => {
       if (res.code !== 0) {
         this.msg.success(`发送失败`);
       }
@@ -242,7 +241,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
 
     this.loading = true;
     this.cdr.detectChanges();
-    this.authenticationService
+    this.authnService
       .login({
         authType: this.loginType,
         state: this.state,
@@ -271,8 +270,8 @@ export class UserLoginComponent implements OnInit, OnDestroy {
           // 清空路由复用信息
           this.reuseTabService.clear();
           // 设置用户Token信息
-          this.authenticationService.auth(res.data);
-          this.authenticationService.navigate({});
+          this.authnService.auth(res.data);
+          this.authnService.navigate({});
         }
         this.cdr.detectChanges();
       });
@@ -287,7 +286,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
   }
 
   getQrCode(): void {
-    this.authenticationService.clearUser();
+    this.authnService.clearUser();
     this.socialsProviderService.scanqrcode(this.socials.qrScan).subscribe(res => {
       if (res.code === 0) {
         if (this.socials.qrScan === 'workweixin') {

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/routes/routes-routing.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/routes/routes.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { NgModule, Type } from '@angular/core';
 import { SharedModule } from '@shared';

+ 26 - 5
maxkey-web-frontend/maxkey-web-app/src/app/service/authentication.service.ts → maxkey-web-frontend/maxkey-web-app/src/app/service/authn.service.ts

@@ -1,23 +1,23 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Injectable, Inject } from '@angular/core';
 import { Router } from '@angular/router';
 import { StartupService } from '@core';
+import { ACLService } from '@delon/acl';
 import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
 import { SettingsService, _HttpClient, User } from '@delon/theme';
 import * as CryptoJS from 'crypto-js';
@@ -29,7 +29,7 @@ import { hostname } from 'os';
 @Injectable({
   providedIn: 'root'
 })
-export class AuthenticationService {
+export class AuthnService {
   redirect_uri: string = '';
 
   constructor(
@@ -91,6 +91,7 @@ export class AuthenticationService {
 
     this.cookieService.set(CONSTS.CONGRESS, authJwt.token);
     this.cookieService.set(CONSTS.ONLINE_TICKET, authJwt.ticket, { domain: subHostName });
+
     if (authJwt.remeberMe) {
       localStorage.setItem(CONSTS.REMEMBER, authJwt.remeberMe);
     }
@@ -99,6 +100,26 @@ export class AuthenticationService {
     this.tokenService.get()?.expired;
   }
 
+  setRoles(aclService: ACLService | null): string[] {
+    let authorities: string[] = JSON.parse(localStorage.getItem(CONSTS.TOKEN) || '')?.authorities || [];
+    if (aclService) {
+      aclService.setRole(authorities);
+    }
+    return authorities;
+  }
+
+  hasRole(role: string): boolean {
+    if (role) {
+      let authorities: string[] = JSON.parse(localStorage.getItem(CONSTS.TOKEN) || '')?.authorities || [];
+      for (let i = 0; i < authorities.length; i++) {
+        if (role == authorities[i]) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
   navigate(authJwt: any) {
     // 重新获取 StartupService 内容,我们始终认为应用信息一般都会受当前用户授权范围而影响
     this.startupService.load().subscribe(() => {

+ 4 - 4
maxkey-web-frontend/maxkey-web-app/src/app/shared/consts.ts

@@ -1,24 +1,24 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 export const CONSTS = {
     CONGRESS: 'congress',
     ONLINE_TICKET: 'online_ticket',
     REDIRECT_URI: 'redirect_uri',
     REMEMBER: 'remember_me',
+    TOKEN: '_token',
     VERSION: 'v3.5.0 GA'
 };

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/shared/shared-delon.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { PageHeaderModule } from '@delon/abc/page-header';
 import { ResultModule } from '@delon/abc/result';

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/app/shared/shared-zorro.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { NzAlertModule } from 'ng-zorro-antd/alert';
 import { NzAvatarModule } from 'ng-zorro-antd/avatar';

+ 4 - 4
maxkey-web-frontend/maxkey-web-app/src/app/shared/shared.module.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { CommonModule } from '@angular/common';
 import { NgModule, Type } from '@angular/core';
@@ -49,6 +48,7 @@ const DIRECTIVES: Array<Type<any>> = [];
     RouterModule,
     ReactiveFormsModule,
     AlainThemeModule.forChild(),
+    DelonACLModule.forRoot(),
     DelonACLModule,
     DelonFormModule,
     ...SHARED_DELON_MODULES,

+ 6 - 4
maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout-nav.component.html

@@ -2,21 +2,23 @@
   <ul nz-menu nzMode="horizontal" nzTheme="dark" style="text-align: center">
     <!--一级菜单-->
     <ng-container *ngFor="let mnav of ls">
-      <li nz-menu-item *ngIf="mnav.children.length == 0" style="min-width: 80px">
-        <a href="#{{ mnav.link }}">{{ mnav.text }}</a>
+      <li nz-menu-item *ngIf="mnav.children.length == 0 && mnav.disabled == false" style="min-width: 80px">
+        <a *ngIf="mnav.externalLink == ''" href="#{{ mnav.link }}">{{ mnav.text }}</a>
+
+        <a *ngIf="mnav.externalLink != ''" href="#{{ mnav.externalLink }}" target="_blank">{{ mnav.text }}</a>
       </li>
       <li nz-submenu nzTitle="{{ mnav.text }}" *ngIf="mnav.children.length > 0">
         <ul>
           <!--二级菜单-->
           <ng-container *ngFor="let snav of mnav.children">
-            <li nz-menu-item *ngIf="snav.children.length == 0">
+            <li nz-menu-item *ngIf="snav.children.length == 0 && mnav.disabled == false">
               <a href="#{{ snav.link }}">{{ snav.text }}</a>
             </li>
             <li nz-submenu nzTitle="{{ snav.text }}" *ngIf="snav.children.length > 0">
               <ul>
                 <!--三级菜单-->
                 <ng-container *ngFor="let tnav of snav.children">
-                  <li nz-menu-item *ngIf="tnav.children.length == 0">
+                  <li nz-menu-item *ngIf="tnav.children.length == 0 && mnav.disabled == false">
                     <a href="#{{ tnav.link }}">{{ tnav.text }}</a>
                   </li>
                 </ng-container>

+ 14 - 4
maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout-nav.component.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { Direction, Directionality } from '@angular/cdk/bidi';
 import { DOCUMENT } from '@angular/common';
@@ -34,6 +33,7 @@ import {
 } from '@angular/core';
 import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
 import { NavigationEnd, Router } from '@angular/router';
+import { ACLService } from '@delon/acl';
 import { Menu, MenuIcon, MenuInner, MenuService, SettingsService } from '@delon/theme';
 import { BooleanInput, InputBoolean, InputNumber, NumberInput, ZoneOutside } from '@delon/util/decorator';
 import { WINDOW } from '@delon/util/token';
@@ -41,6 +41,7 @@ import type { NzSafeAny } from 'ng-zorro-antd/core/types';
 import { Subject } from 'rxjs';
 import { filter, takeUntil } from 'rxjs/operators';
 
+import { AuthnService } from '../../service/authn.service';
 import { LayoutDefaultOptions } from './types';
 
 export interface Nav extends MenuInner {
@@ -89,6 +90,8 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy {
 
   constructor(
     private menuSrv: MenuService,
+    private authnService: AuthnService,
+    private aclService: ACLService,
     private settings: SettingsService,
     private router: Router,
     private render: Renderer2,
@@ -280,6 +283,8 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy {
   }
 
   ngOnInit(): void {
+    this.aclService.setFull(false);
+    this.authnService.setRoles(this.aclService);
     const { doc, router, destroy$, menuSrv, settings, cdr } = this;
     this.bodyEl = doc.querySelector('body');
     this.openedByUrl(router.url);
@@ -295,6 +300,11 @@ export class LayoutDefaultNavComponent implements OnInit, OnDestroy {
             i._hidden = true;
           }
         }
+
+        if (i.acl && !this.authnService.hasRole(`${i.acl}`)) {
+          i.disabled = true;
+        }
+
         if (this.openStrictly) {
           i._open = i.open != null ? i.open : false;
         }

+ 6 - 6
maxkey-web-frontend/maxkey-web-app/src/app/theme/layout-default/layout.module.ts

@@ -1,24 +1,23 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
-
+import { DelonACLModule } from '@delon/acl';
 import { NzAvatarModule } from 'ng-zorro-antd/avatar';
 import { NzBadgeModule } from 'ng-zorro-antd/badge';
 import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
@@ -44,6 +43,7 @@ const COMPONENTS = [
   imports: [
     CommonModule,
     RouterModule,
+    DelonACLModule.forRoot(),
     NzToolTipModule,
     NzIconModule,
     NzAvatarModule,
@@ -54,4 +54,4 @@ const COMPONENTS = [
   declarations: COMPONENTS,
   exports: COMPONENTS
 })
-export class LayoutDefaultModule {}
+export class LayoutDefaultModule { }

+ 13 - 1
maxkey-web-frontend/maxkey-web-app/src/assets/app-data.json

@@ -16,6 +16,7 @@
           "icon": "anticon-home",
           "link": "/dashboard/home",
           "open":false,
+          "acl": "ROLE_USER",
           "children": []
         },
         {
@@ -24,6 +25,7 @@
           "link": "/access/sessions",
           "icon": "anticon-cluster",
           "open":false,
+          "acl": "ROLE_USER",
           "children": []
         },
         {
@@ -32,12 +34,14 @@
           "link": "/config/setting",
           "icon": "anticon-setting",
           "open":false,
+          "acl": "ROLE_USER",
           "children": [
             {
               "text": "我的资料",
               "i18n": "mxk.menu.config.profile",
               "link": "/config/profile",
               "icon": "anticon-appstore",
+              "acl": "ROLE_USER",
               "children": []
             },
             {
@@ -45,6 +49,7 @@
               "i18n": "mxk.menu.config.password",
               "link": "/config/password",
               "icon": "anticon-control",
+              "acl": "ROLE_USER",
               "children": []
             },
             {
@@ -52,6 +57,7 @@
               "i18n": "mxk.menu.config.socialsassociate",
               "link": "/config/socialsassociate",
               "icon": "anticon-comment",
+              "acl": "ROLE_USER",
               "children": []
             },
             {
@@ -59,6 +65,7 @@
               "i18n": "mxk.menu.config.timebased",
               "link": "/config/timebased",
               "icon": "anticon-send",
+              "acl": "ROLE_USER",
               "children": []
             }
           ]
@@ -69,12 +76,14 @@
           "link": "/audit/audit-logins",
           "icon": "anticon-history",
           "open":true,
+          "acl": "ROLE_USER",
           "children": [
             {
               "text": "登录日志",
               "i18n": "mxk.menu.audit.logins",
               "link": "/audit/audit-logins",
               "icon": "anticon-audit",
+              "acl": "ROLE_USER",
               "children": []
             },
             {
@@ -82,6 +91,7 @@
               "i18n": "mxk.menu.audit.loginapps",
               "link": "/audit/audit-login-apps",
               "icon": "anticon-audit",
+              "acl": "ROLE_USER",
               "children": []
             }
           ]
@@ -90,8 +100,10 @@
         {
           "text": "后台",
           "i18n": "mxk.menu.mgt",
-          "link": "/mgt",
+          "link": "/authz/mgt",
+          "externalLink": "/authz/mgt",
           "icon": "anticon-cluster",
+          "acl": "ROLE_ADMINISTRATORS",
           "open":false,
           "children": []
         }

+ 1 - 1
maxkey-web-frontend/maxkey-web-app/src/assets/i18n/zh-CN.json

@@ -204,7 +204,7 @@
     },
     "accounts":{
       "userId":"用户编号",
-      "username":"登录账号",
+      "username":"登录",
       "displayName":"用户名",
       "appName":"应用名称",
       "appId":"应用编号",

+ 3 - 4
maxkey-web-frontend/maxkey-web-app/src/environments/environment.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 // This file can be replaced during build by using the `fileReplacements` array.
 // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.

+ 5 - 4
maxkey-web-frontend/maxkey-web-app/src/style-icons-auto.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
 
 /*
  * Automatically generated by 'ng g ng-alain:plugin icon'
@@ -107,6 +106,7 @@ import {
   DashOutline,
   FileProtectOutline,
   HistoryOutline,
+  UserAddOutline,
   AuditOutline
 } from '@ant-design/icons-angular/icons';
 import { QR_DEFULAT_CONFIG } from '@delon/abc/qr';
@@ -198,5 +198,6 @@ export const ICONS_AUTO = [
   DashOutline,
   FileProtectOutline,
   HistoryOutline,
+  UserAddOutline,
   AuditOutline
 ];

+ 1 - 3
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/AppListController.java

@@ -1,5 +1,5 @@
 /*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ package org.maxkey.web.contorller;
 import java.util.List;
 
 import org.maxkey.authn.annotation.CurrentUser;
-import org.maxkey.authn.web.AuthorizationUtils;
 import org.maxkey.constants.ConstsStatus;
 import org.maxkey.crypto.password.PasswordReciprocal;
 import org.maxkey.entity.Accounts;
@@ -115,7 +114,6 @@ public class AppListController {
     		@ModelAttribute Accounts account,
             @CurrentUser UserInfo currentUser) {
         Accounts appUsers = new Accounts();
-
         if (credential == Apps.CREDENTIALS.USER_DEFINED) {
             appUsers = accountsService.load(new Accounts(currentUser.getId(), account.getAppId()));
             if (appUsers == null) {

+ 9 - 11
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/OneTimePasswordController.java

@@ -1,5 +1,5 @@
 /*
- * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
+ * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,12 +18,13 @@
 package org.maxkey.web.contorller;
 
 import java.awt.image.BufferedImage;
-import java.util.Base64;
 import java.util.HashMap;
+
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.lang3.StringUtils;
 import org.maxkey.authn.annotation.CurrentUser;
 import org.maxkey.crypto.Base32Utils;
+import org.maxkey.crypto.Base64Utils;
 import org.maxkey.crypto.password.PasswordReciprocal;
 import org.maxkey.entity.Message;
 import org.maxkey.entity.UserInfo;
@@ -31,7 +32,6 @@ import org.maxkey.password.onetimepwd.algorithm.OtpKeyUriFormat;
 import org.maxkey.password.onetimepwd.algorithm.OtpSecret;
 import org.maxkey.persistence.service.UserInfoService;
 import org.maxkey.util.RQCodeUtils;
-import org.maxkey.web.image.ImageEndpoint;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -60,7 +60,8 @@ public class OneTimePasswordController {
 
     @RequestMapping(value = {"/timebased"})
     @ResponseBody
-    public ResponseEntity<?> timebased(@RequestParam String generate,@CurrentUser UserInfo currentUser) {
+    public ResponseEntity<?> timebased(
+    			@RequestParam String generate,@CurrentUser UserInfo currentUser) {
         HashMap<String,Object >timebased =new HashMap<String,Object >();
         
         generate(generate,currentUser);
@@ -72,6 +73,8 @@ public class OneTimePasswordController {
         String otpauth = otpKeyUriFormat.format(currentUser.getUsername());
         byte[] byteSharedSecret = Base32Utils.decode(sharedSecret);
         String hexSharedSecret = Hex.encodeHexString(byteSharedSecret);
+        BufferedImage bufferedImage  =  RQCodeUtils.write2BufferedImage(otpauth, "gif", 300, 300);
+    	String rqCode = Base64Utils.encodeImage(bufferedImage);
         
         timebased.put("displayName", currentUser.getDisplayName());
         timebased.put("username", currentUser.getUsername());
@@ -79,7 +82,7 @@ public class OneTimePasswordController {
         timebased.put("period", otpKeyUriFormat.getPeriod());
         timebased.put("sharedSecret", sharedSecret);
         timebased.put("hexSharedSecret", hexSharedSecret);
-        timebased.put("rqCode", genRqCode(otpauth));
+        timebased.put("rqCode", rqCode);
         return new Message<HashMap<String,Object >>(timebased).buildResponse();
     }
 
@@ -96,10 +99,5 @@ public class OneTimePasswordController {
             
         }
     }
-
-    public  String genRqCode(String otpauth) {
-        BufferedImage bufferedImage  =  RQCodeUtils.write2BufferedImage(otpauth, "gif", 300, 300);
-        byte[] imageByte = ImageEndpoint.bufferedImage2Byte(bufferedImage);
-        return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageByte);
-    }
+    
 }