diff --git a/home/docs/help/template-marketplace-img/asset-detail.png b/home/docs/help/template-marketplace-img/asset-detail.png new file mode 100644 index 00000000000..53840b704b2 Binary files /dev/null and b/home/docs/help/template-marketplace-img/asset-detail.png differ diff --git a/home/docs/help/template-marketplace-img/asset-upgrade.png b/home/docs/help/template-marketplace-img/asset-upgrade.png new file mode 100644 index 00000000000..6497ff843dc Binary files /dev/null and b/home/docs/help/template-marketplace-img/asset-upgrade.png differ diff --git a/home/docs/help/template-marketplace-img/detail-faq.png b/home/docs/help/template-marketplace-img/detail-faq.png new file mode 100644 index 00000000000..a155258d8ba Binary files /dev/null and b/home/docs/help/template-marketplace-img/detail-faq.png differ diff --git a/home/docs/help/template-marketplace-img/detail-info.png b/home/docs/help/template-marketplace-img/detail-info.png new file mode 100644 index 00000000000..8795fb34bf4 Binary files /dev/null and b/home/docs/help/template-marketplace-img/detail-info.png differ diff --git a/home/docs/help/template-marketplace-img/detail-version.png b/home/docs/help/template-marketplace-img/detail-version.png new file mode 100644 index 00000000000..0e5ddf13cba Binary files /dev/null and b/home/docs/help/template-marketplace-img/detail-version.png differ diff --git a/home/docs/help/template-marketplace-img/download.png b/home/docs/help/template-marketplace-img/download.png new file mode 100644 index 00000000000..a2494d5fb4c Binary files /dev/null and b/home/docs/help/template-marketplace-img/download.png differ diff --git a/home/docs/help/template-marketplace-img/email-login.png b/home/docs/help/template-marketplace-img/email-login.png new file mode 100644 index 00000000000..04c582475b3 Binary files /dev/null and b/home/docs/help/template-marketplace-img/email-login.png differ diff --git a/home/docs/help/template-marketplace-img/hover-window-guest.png b/home/docs/help/template-marketplace-img/hover-window-guest.png new file mode 100644 index 00000000000..2c99b20363b Binary files /dev/null and b/home/docs/help/template-marketplace-img/hover-window-guest.png differ diff --git a/home/docs/help/template-marketplace-img/hover-window-user.png b/home/docs/help/template-marketplace-img/hover-window-user.png new file mode 100644 index 00000000000..4fe82ff5916 Binary files /dev/null and b/home/docs/help/template-marketplace-img/hover-window-user.png differ diff --git a/home/docs/help/template-marketplace-img/search-category.png b/home/docs/help/template-marketplace-img/search-category.png new file mode 100644 index 00000000000..ecbf4d2d724 Binary files /dev/null and b/home/docs/help/template-marketplace-img/search-category.png differ diff --git a/home/docs/help/template-marketplace-img/search-name.png b/home/docs/help/template-marketplace-img/search-name.png new file mode 100644 index 00000000000..7467dac8d95 Binary files /dev/null and b/home/docs/help/template-marketplace-img/search-name.png differ diff --git a/home/docs/help/template-marketplace-img/search.png b/home/docs/help/template-marketplace-img/search.png new file mode 100644 index 00000000000..da1a051daa5 Binary files /dev/null and b/home/docs/help/template-marketplace-img/search.png differ diff --git a/home/docs/help/template-marketplace-img/share.png b/home/docs/help/template-marketplace-img/share.png new file mode 100644 index 00000000000..2a5c4ee3d9b Binary files /dev/null and b/home/docs/help/template-marketplace-img/share.png differ diff --git a/home/docs/help/template-marketplace-img/sign-up.png b/home/docs/help/template-marketplace-img/sign-up.png new file mode 100644 index 00000000000..4b6de257967 Binary files /dev/null and b/home/docs/help/template-marketplace-img/sign-up.png differ diff --git a/home/docs/help/template-marketplace-img/user-center-asset.png b/home/docs/help/template-marketplace-img/user-center-asset.png new file mode 100644 index 00000000000..db4d6a1a922 Binary files /dev/null and b/home/docs/help/template-marketplace-img/user-center-asset.png differ diff --git a/home/docs/help/template-marketplace-img/user-center-star-detail.png b/home/docs/help/template-marketplace-img/user-center-star-detail.png new file mode 100644 index 00000000000..e7fe46e73e6 Binary files /dev/null and b/home/docs/help/template-marketplace-img/user-center-star-detail.png differ diff --git a/home/docs/help/template-marketplace-img/user-center-star.png b/home/docs/help/template-marketplace-img/user-center-star.png new file mode 100644 index 00000000000..91f1ae99dd5 Binary files /dev/null and b/home/docs/help/template-marketplace-img/user-center-star.png differ diff --git a/home/docs/help/template-marketplace-img/user-center-upload.png b/home/docs/help/template-marketplace-img/user-center-upload.png new file mode 100644 index 00000000000..e8fca988dd2 Binary files /dev/null and b/home/docs/help/template-marketplace-img/user-center-upload.png differ diff --git a/home/docs/help/template_marketplace.md b/home/docs/help/template_marketplace.md new file mode 100644 index 00000000000..4156fe71323 --- /dev/null +++ b/home/docs/help/template_marketplace.md @@ -0,0 +1,152 @@ +--- +id: template_marketplace +title: Template Marketplace +sidebar_label: Template Marketplace +--- + +> Hertzbeat official template marketplace: users can freely upload, download, view, search and share monitoring template files. + +## Basic Functions + +### Search + +💡 Guest availability + +> Display template name, brief description, favorites, downloads, views and other information + +1. **No filter: displayed in order of upload** + + ![search.png](template-marketplace-img/search.png) + +2. **Filtering by category: currently divided into six categories** + + > **📋Todo:** develop tag function, subdivided within the category, such as database monitoring template can be divided into MySQL, Oracle, etc. + + ![search-category.png](template-marketplace-img/search-category.png) + +3. **Fuzzy search by Title** + + ![search-name.png](template-marketplace-img/search-name.png) + +4. **Hover window function: download the latest version, view details, favorite/un-favorite** + + > Show if the user has favorites after logging in + + ![img.png](template-marketplace-img/hover-window-guest.png)![img_1.png](template-marketplace-img/hover-window-user.png) + +5. **Sort: Eight Sorting Methods** + + > **📋Todo:** Waiting for the actual installation + +### Template Detail + +💡 Guest availability + + > Display basic information about the template, such as name, author, update time, version information, etc. + +1. **Info: Summary information, detailed information and other information** + + > **📋Todo:** Upgrade to MarkDown format + + ![img.png](template-marketplace-img/detail-info.png) + +2. **Version: Historical version download, sharing and basic information display** + + > **📋Todo:** Set up a view function for each historical version to display information such as the version description. + + ![img.png](template-marketplace-img/detail-version.png) + +3. **FAQ** + + > **📋Todo:** Discussion or issue Q&A section + + ![img.png](template-marketplace-img/detail-faq.png) + +4. **Download** + + > The latest version can be downloaded directly from the list hover window. + > The latest version can also be downloaded directly from the template detail page. + > The historical version can be downloaded from the version page. + + ![img.png](template-marketplace-img/download.png) + +5. **Share** + + > Template details page to share the latest version. + > Version page to share historical versions. + > Sharing will automatically copy the sharing URL to the clipboard, and the person being shared can download the file via that URL + > + > **📋Todo:** Shared template detail page is accessed through the URL of the shared template, and the shared person is free to choose whether to download or not. + + ![img.png](template-marketplace-img/share.png) + +### User Center + +💡 User availability + + > Provide asset management, collection management and upload function +> + > **📋Todo:** Overview page, notification page, user settings page + +1. **Asset: Manage all templates uploaded by user themselves** + + > Provides the ability to download the latest version and view details + > + > **📋Todo:** Function to update template information + + ![img_1.png](template-marketplace-img/user-center-asset.png) + + ![img.png](template-marketplace-img/asset-detail.png) + +2. **Version Upgrade** + + > The user defines the new version number under this template family, updates the version information, and uploads the latest version of the file + + ![img.png](template-marketplace-img/asset-upgrade.png) + +3. **Star** + + ![img.png](template-marketplace-img/user-center-star.png) + + ![img.png](template-marketplace-img/user-center-star-detail.png) + +4. **Upload** + + > Create a new template series and upload the first version of the file + > + > Fill in the template name, select the template category, fill in the description information and version information, and upload files + + ![img.png](template-marketplace-img/user-center-upload.png) + +### Sign Up & Login + +💡 Guest availability + +1. **Sign up** + + > Usernames can be duplicated, but email addresses are unique + > + > **📋Todo:** Captcha function, email verification function + + ![img.png](template-marketplace-img/sign-up.png) + +2. **Login** + + > **📋Todo:** Captcha function and forgot password function + + ![img.png](template-marketplace-img/email-login.png) + +## Development Steps + + > Download `template-marketplace/hertzbeat-template-hub` and `template-marketplace/hertzbeat-template-hub-web-app` projects respectively + + The front-end project in accordance with README.md directly start + + The back-end project steps: + + 1. Run the `sql` script in the `template-marketplace/hertzbeat-template-hub/sql` to create database tables + 2. Install MinIO + 3. Config `MySQL` and `MinIO` in the `application.yml` + 4. Start the back-end project + +Other issues can be fed back through the communication group ISSUE! diff --git a/home/sidebars.json b/home/sidebars.json index 4b32c85d93b..25c730e05f4 100755 --- a/home/sidebars.json +++ b/home/sidebars.json @@ -384,6 +384,13 @@ "help/issue" ] }, + { + "type": "category", + "label": "Template Marketplace", + "items": [ + "help/template_marketplace" + ] + }, { "type": "category", "label": "Others", diff --git a/template-marketplace/hertzbeat-template-hub-web-app/.editorconfig b/template-marketplace/hertzbeat-template-hub-web-app/.editorconfig new file mode 100644 index 00000000000..59d9a3a3e73 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/template-marketplace/hertzbeat-template-hub-web-app/.gitignore b/template-marketplace/hertzbeat-template-hub-web-app/.gitignore new file mode 100644 index 00000000000..cc7b141350f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/.gitignore @@ -0,0 +1,42 @@ +# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/template-marketplace/hertzbeat-template-hub-web-app/.prettierrc.js b/template-marketplace/hertzbeat-template-hub-web-app/.prettierrc.js new file mode 100644 index 00000000000..4578bf48815 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/.prettierrc.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +module.exports = { + singleQuote: true, + useTabs: false, + printWidth: 140, + tabWidth: 2, + semi: true, + htmlWhitespaceSensitivity: 'strict', + arrowParens: 'avoid', + bracketSpacing: true, + proseWrap: 'preserve', + trailingComma: 'none', + endOfLine: 'lf' +}; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/README.md b/template-marketplace/hertzbeat-template-hub-web-app/README.md new file mode 100644 index 00000000000..9dbef66047d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/README.md @@ -0,0 +1,27 @@ +# HertzbeatTemplateHubWebApp + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.5. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. diff --git a/template-marketplace/hertzbeat-template-hub-web-app/angular.json b/template-marketplace/hertzbeat-template-hub-web-app/angular.json new file mode 100644 index 00000000000..11b910d9542 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/angular.json @@ -0,0 +1,186 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "hertzbeat-template-hub-web-app": { + "projectType": "application", + "root": "", + "sourceRoot": "src", + "prefix": "app", + "schematics": { + "@schematics/angular:component": { + "style": "css" + }, + "@schematics/angular:application": { + "strict": true + } + }, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "preserveSymlinks": true, + "outputPath": "dist", + "index": "src/index.html", + "main": "src/main.ts", + "tsConfig": "tsconfig.app.json", + "polyfills": [ + "zone.js" + ], + "assets": [ + "src/assets", + "src/favicon.ico", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + }, + { + "glob": "**/*", + "input": "node_modules/monaco-editor/min/vs", + "output": "/assets/vs/" + } + ], + "styles": [ + "src/styles.css", + "node_modules/ng-zorro-antd/ng-zorro-antd.min.css", + "node_modules/slick-carousel/slick/slick.scss", + "node_modules/slick-carousel/slick/slick-theme.scss" + ], + "scripts": [ + "node_modules/jquery/dist/jquery.min.js", + "node_modules/slick-carousel/slick/slick.min.js" + ], + "allowedCommonJsDependencies": [ + "ajv", + "ajv-formats", + "mockjs", + "date-fns", + "file-saver", + "extend" + ], + "stylePreprocessorOptions": { + "includePaths": [ + "node_modules/" + ] + } + }, + "configurations": { + "production": { + "extractLicenses": false, + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "outputHashing": "all", + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "6mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "proxyConfig": "proxy.conf.json", + "buildTarget": "hertzbeat-template-hub-web-app:build" + }, + "configurations": { + "production": { + "buildTarget": "hertzbeat-template-hub-web-app:build:production" + }, + "development": { + "buildTarget": "hertzbeat-template-hub-web-app:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "hertzbeat-template-hub-web-app:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": [ + "zone.js", + "zone.js/testing" + ], + "tsConfig": "tsconfig.spec.json", + "assets": [ + "src/assets", + { + "glob": "**/*", + "input": "public" + } + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": [ + "src/**/*.ts", + "src/**/*.html" + ] + } + }, + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "hertzbeat-template-hub-web-app:serve" + }, + "configurations": { + "production": { + "devServerTarget": "hertzbeat-template-hub-web-app:serve:production" + } + } + } + } + } + }, + "cli": { + "packageManager": "yarn", + "schematicCollections": [ + "@schematics/angular", + "hertzbeat-template-hub-web-app" + ], + "analytics": false + }, + "schematics": { + "@angular-eslint/schematics:application": { + "setParserOptionsProject": true + }, + "@angular-eslint/schematics:library": { + "setParserOptionsProject": true + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/ng-alain.json b/template-marketplace/hertzbeat-template-hub-web-app/ng-alain.json new file mode 100644 index 00000000000..ff78a68b9ac --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/ng-alain.json @@ -0,0 +1,13 @@ +{ + "$schema": "./node_modules/ng-alain/schema.json", + "theme": { + "list": [ + { + "theme": "dark" + }, + { + "theme": "compact" + } + ] + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/package.json b/template-marketplace/hertzbeat-template-hub-web-app/package.json new file mode 100644 index 00000000000..e16b6bb5386 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/package.json @@ -0,0 +1,66 @@ +{ + "name": "hertzbeat-template-hub-web-app", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test" + }, + "private": true, + "dependencies": { + "@angular/animations": "^18.2.5", + "@angular/common": "^18.2.0", + "@angular/compiler": "^18.2.0", + "@angular/core": "^18.2.5", + "@angular/forms": "^18.2.0", + "@angular/platform-browser": "^18.2.0", + "@angular/platform-browser-dynamic": "^18.2.0", + "@angular/router": "^18.2.0", + "@delon/abc": "^18.1.0", + "@delon/cache": "^18.1.0", + "@delon/form": "^18.1.0", + "@delon/theme": "^18.1.0", + "@delon/util": "^18.1.0", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "angular-tag-cloud-module": "^17.0.1", + "echarts": "^5.5.1", + "file-saver": "^2.0.5", + "jquery": "^3.7.1", + "ng-zorro-antd": "^18.1.1", + "ngx-color-picker": "^17.0.0", + "ngx-echarts": "^18.0.0", + "rxjs": "~7.8.0", + "screenfull": "^6.0.2", + "slick-carousel": "^1.8.1", + "tslib": "^2.7.0", + "zone.js": "~0.14.10" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^18.2.5", + "@angular/cli": "^18.2.5", + "@angular/compiler-cli": "^18.2.0", + "@types/file-saver": "^2.0.7", + "@types/jasmine": "~5.1.0", + "@types/node": "^22.7.7", + "jasmine-core": "~5.2.0", + "jasmine-spec-reporter": "^7.0.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.2.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.1.0", + "ng-alain": "^18.1.0", + "node-fetch": "^3.3.2", + "prettier": "^3.3.3", + "purgecss": "^6.0.0", + "ts-node": "^10.9.2", + "typescript": "~5.5.2" + }, + "description": "This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.5.", + "main": "index.js", + "author": "", + "license": "ISC" +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/proxy.conf.json b/template-marketplace/hertzbeat-template-hub-web-app/proxy.conf.json new file mode 100644 index 00000000000..573f488e5c3 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/proxy.conf.json @@ -0,0 +1,8 @@ +{ + "/api/*": { + "target": "http://localhost:8080/api", + "secure": false, + "changeOrigin": true, + "logLevel": "debug" + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/public/favicon.ico b/template-marketplace/hertzbeat-template-hub-web-app/public/favicon.ico new file mode 100644 index 00000000000..7a6cba72e7a Binary files /dev/null and b/template-marketplace/hertzbeat-template-hub-web-app/public/favicon.ico differ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.html new file mode 100644 index 00000000000..60eabc73c61 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.html @@ -0,0 +1,20 @@ + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.ts new file mode 100644 index 00000000000..4cb6470145a --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.component.ts @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnInit} from '@angular/core'; +import {RouterOutlet} from "@angular/router"; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + standalone: true, + imports: [ + RouterOutlet + ] +}) + +export class AppComponent implements OnInit { + title = 'hertzbeat-template-hub-web-app'; + + constructor() { + } + + ngOnInit() { + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.config.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.config.ts new file mode 100644 index 00000000000..2a11a485008 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.config.ts @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core'; +import {provideRouter} from '@angular/router'; + +import {routes} from './routes/routes-routing.module'; +import {HTTP_INTERCEPTORS, HttpClientModule} from "@angular/common/http"; +import {DefaultInterceptor} from "@core"; +import {provideAnimations} from "@angular/platform-browser/animations"; +import {TemplateService} from "./service/template.service"; +import {LocalStorageService} from "./service/local-storage.service"; +import {DataService} from "./service/data.service"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({eventCoalescing: true}), + provideRouter(routes), + provideAnimations(), + importProvidersFrom(HttpClientModule), + { + provide: HTTP_INTERCEPTORS, + useClass: DefaultInterceptor, + multi: true, + }, + TemplateService, + LocalStorageService, + DataService + ] +}; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.module.ts new file mode 100644 index 00000000000..319ad9fbb59 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/app.module.ts @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {BrowserModule} from '@angular/platform-browser'; +import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {NzMessageModule} from 'ng-zorro-antd/message'; +import {NzNotificationModule} from 'ng-zorro-antd/notification'; +import {AppComponent} from "./app.component"; +import {RouterOutlet} from "@angular/router"; +import {NgxEchartsModule} from "ngx-echarts"; +import {GlobalConfigModule} from "./global-config.module"; +import {CoreModule} from "./core/core.module"; +import {NzIconModule} from "ng-zorro-antd/icon"; + +// const INTERCEPTOR_PROVIDES = [{ provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true }]; + +@NgModule({ + declarations: [], + imports: [ + BrowserModule, + BrowserAnimationsModule, + FormsModule, + NzMessageModule, + NzNotificationModule, + RouterOutlet, + AppComponent, + ReactiveFormsModule, + CoreModule, + NzIconModule, + GlobalConfigModule.forRoot(), + NgxEchartsModule.forRoot({ + echarts: () => import((`echarts`)) + }), + ], +}) +export class AppModule { +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/core.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/core.module.ts new file mode 100644 index 00000000000..70e9da75d8e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/core.module.ts @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, Optional, SkipSelf } from '@angular/core'; + +import { throwIfAlreadyLoaded } from './module-import-guard'; + +@NgModule({ + providers: [] +}) +export class CoreModule { + constructor(@Optional() @SkipSelf() parentModule: CoreModule) { + throwIfAlreadyLoaded(parentModule, 'CoreModule'); + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/guard/detect-auth-guard.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/guard/detect-auth-guard.ts new file mode 100644 index 00000000000..0c2c024d1e4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/guard/detect-auth-guard.ts @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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} from '@angular/core'; +import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; +import {NzNotificationService} from 'ng-zorro-antd/notification'; +import {Observable} from 'rxjs'; + +import {LocalStorageService} from '../../service/local-storage.service'; + +@Injectable({ + providedIn: 'root' +}) +export class DetectAuthGuard implements CanActivate { + constructor( + private localStorageSvc: LocalStorageService, + private notifySvc: NzNotificationService, + private router: Router + ) {} + + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable | Promise | boolean | UrlTree { + let activate = this.localStorageSvc.hasAuthorizationToken(); + if (!activate) { + setTimeout(() => { + this.notifySvc.warning('登录', ''); + this.router.navigateByUrl('/passport/login'); + }); + } + return activate; + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/index.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/index.ts new file mode 100644 index 00000000000..17ef8d5c6cf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 * from './module-import-guard'; +export * from './interceptor/default.interceptor'; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/interceptor/default.interceptor.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/interceptor/default.interceptor.ts new file mode 100644 index 00000000000..7e2f45b47d7 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/interceptor/default.interceptor.ts @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpHeaders, + HttpInterceptor, + HttpRequest, + HttpResponse, + HttpResponseBase +} from '@angular/common/http'; +import { Injectable, Injector } from '@angular/core'; +import { Router } from '@angular/router'; +import { ALAIN_I18N_TOKEN, _HttpClient } from '@delon/theme'; +import { environment } from '@env/environment'; +import { NzNotificationService } from 'ng-zorro-antd/notification'; +import { BehaviorSubject, Observable, of, throwError } from 'rxjs'; +import { catchError, filter, mergeMap, switchMap, take } from 'rxjs/operators'; + +import {Message} from "../../pojo/Message"; +import {AuthService} from '../../service/auth.service'; +import {LocalStorageService} from '../../service/local-storage.service'; + +const CODE_MESSAGE: { [key: number]: string } = { + 400: 'Request Illegal Content, No Response.', + 401: 'Auth Error.', + 403: 'No Permission For This Request.', + 404: 'Not Found.', + 406: 'Request Illegal Content.', + 409: 'Request Conflict.', + 410: 'Request Resource Already Deleted.', + 422: 'Validate Error.', + 500: 'Server Error Happen.', + 502: 'Gateway Error.', + 503: 'Service Not Available, Try After.', + 504: 'Gateway Timeout.' +}; + +@Injectable() +export class DefaultInterceptor implements HttpInterceptor { + private notified = false; + // Whether token is refreshing + private refreshToking = false; + private refreshToken$: BehaviorSubject = new BehaviorSubject(null); + + constructor(private injector: Injector, private authSvc: AuthService, private storageSvc: LocalStorageService) {} + + private get notification(): NzNotificationService { + return this.injector.get(NzNotificationService); + } + + private get http(): _HttpClient { + return this.injector.get(_HttpClient); + } + + private goTo(url: string): void { + setTimeout(() => { + this.injector.get(Router).navigateByUrl(url); + this.notified = false; + }); + } + + private checkStatus(ev: HttpResponseBase): void { + const errorText = CODE_MESSAGE[ev.status] || ev.statusText; + console.warn(` ${ev.status}: ${ev.url}`, errorText); + if (ev.status == 403) { + this.notification.error(` ${ev.status}: ${errorText}`, ''); + } else { + this.notification.error(` ${ev.status}: ${ev.url}`, errorText); + } + } + + /** + * refresh Token request + */ + private refreshTokenRequest(): Observable> { + const refreshToken = this.storageSvc.getRefreshToken(); + if (refreshToken == null) { + return throwError('refreshToken is null.'); + } + return this.authSvc.refreshToken(refreshToken); + } + + private tryRefreshToken(ev: HttpResponseBase, req: HttpRequest, next: HttpHandler): Observable { + // 1, redirect to login page if this request is used for refreshing token + if ([`/api/auth/refresh`].some(url => req.url.includes(url))) { + this.toLogin(); + return throwError(ev); + } + // 2, if `refreshToking` is true, means that the refreshing token request is in progress + // All requests will be suspended and wait for the refreshing token request to complete + if (this.refreshToking) { + return this.refreshToken$.pipe( + filter(v => !!v), + take(1), + switchMap(() => next.handle(this.reAttachToken(req))) + ); + } + // 3、try refreshing Token + this.refreshToking = true; + this.refreshToken$.next(null); + return this.refreshTokenRequest().pipe( + switchMap(res => { + // Check whether the TOKEN is correct + this.refreshToking = false; + if (res.code === 0 && res.data != undefined) { + let token = res.data.token; + let refreshToken = res.data.refreshToken; + if (token != undefined) { + this.storageSvc.storageAuthorizationToken(token); + this.storageSvc.storageRefreshToken(refreshToken); + // notifies subsequent requests to continue + this.refreshToken$.next(token); + return next.handle(this.reAttachToken(req)); + } else { + console.warn(`flush new token failed. ${res.msg}`); + return throwError('flush new token failed.'); + } + } else { + console.warn(`flush new token failed. ${res.msg}`); + return throwError('flush new token failed.'); + } + }), + catchError(err => { + // refreshing token is failed, redirect to login page + console.warn(`flush new token failed. ${err.msg}`); + this.refreshToking = false; + this.toLogin(); + return throwError(err); + }) + ); + } + + private reAttachToken(req: HttpRequest): HttpRequest { + let token = this.storageSvc.getAuthorizationToken(); + return req.clone({ + setHeaders: { + Authorization: `Bearer ${token}` + } + }); + } + + private toLogin(): void { + if (!this.notified) { + this.notified = true; + this.goTo('/login'); + } + } + + private fillHeaders(headers?: HttpHeaders): { [name: string]: string } { + const res: { [name: string]: string } = {}; + const lang = this.injector.get(ALAIN_I18N_TOKEN).currentLang; + if (!headers?.has('Accept-Language') && lang) { + res['Accept-Language'] = lang; + } + let token = this.storageSvc.getAuthorizationToken(); + if (token !== null) { + res['Authorization'] = `Bearer ${token}`; + } + return res; + } + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + let url = req.url; + if (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('.')) { + const { baseUrl } = environment.api; + url = baseUrl + (baseUrl?.endsWith('/') && url.startsWith('/') ? url.substring(1) : url); + } + const newReq = req.clone({ url, setHeaders: this.fillHeaders(req.headers) }); + return next.handle(newReq).pipe( + mergeMap(httpEvent => { + if (httpEvent instanceof HttpResponseBase) { + return of(httpEvent); + } else { + return of(httpEvent); + } + }), + catchError((err: any) => { + console.error("err:",err); + // handle failed response and token expired + switch (err.status) { + case 401: + console.log('检测到401了') + return this.tryRefreshToken(err, newReq, next); + case 404: + case 500: + this.goTo(`/exception/${err.status}?url=${req.urlWithParams}`); + break; + case 400: + let resp = new HttpResponse({ + body: err.error, + headers: err.headers, + status: err.status, + statusText: err.statusText + }); + return of(resp); + default: + break; + } + this.checkStatus(err); + return throwError(err.error); + }) + ); + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/module-import-guard.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/module-import-guard.ts new file mode 100644 index 00000000000..333500797cf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/core/module-import-guard.ts @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 function throwIfAlreadyLoaded(parentModule: any, moduleName: string): void { + if (parentModule) { + throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`); + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/global-config.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/global-config.module.ts new file mode 100644 index 00000000000..3e8ba7fc997 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/global-config.module.ts @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; +import { DelonACLModule } from '@delon/acl'; +import { AlainThemeModule } from '@delon/theme'; + +import { throwIfAlreadyLoaded } from '@core'; + +import { environment } from '@env/environment'; + +const alainModules: any[] = [AlainThemeModule.forRoot(), DelonACLModule]; +import { NzConfig, NZ_CONFIG } from 'ng-zorro-antd/core/config'; + +const ngZorroConfig: NzConfig = {}; + +const zorroProvides = [{ provide: NZ_CONFIG, useValue: ngZorroConfig }]; + +@NgModule({ + imports: [...alainModules, ...(environment.modules || [])] +}) +export class GlobalConfigModule { + constructor(@Optional() @SkipSelf() parentModule: GlobalConfigModule) { + throwIfAlreadyLoaded(parentModule, 'GlobalConfigModule'); + } + + static forRoot(): ModuleWithProviders { + return { + ngModule: GlobalConfigModule, + providers: [...zorroProvides] + }; + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/blank/blank.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/blank/blank.component.ts new file mode 100644 index 00000000000..6e2b08c3d8b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/blank/blank.component.ts @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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'; + +@Component({ + selector: 'layout-blank', + template: ` `, + host: { + '[class.alain-blank]': 'true' + } +}) +export class LayoutBlankComponent {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/layout.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/layout.module.ts new file mode 100644 index 00000000000..6365030fedb --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/layout.module.ts @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { GlobalFooterModule } from '@delon/abc/global-footer'; +import { NoticeIconModule } from '@delon/abc/notice-icon'; +import { AlainThemeModule } from '@delon/theme'; +import { LayoutDefaultModule } from '@delon/theme/layout-default'; +import { SettingDrawerModule } from '@delon/theme/setting-drawer'; +import { ThemeBtnModule } from '@delon/theme/theme-btn'; +import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete'; +import { NzAvatarModule } from 'ng-zorro-antd/avatar'; +import { NzBadgeModule } from 'ng-zorro-antd/badge'; +import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; +import { NzFormModule } from 'ng-zorro-antd/form'; +import { NzGridModule } from 'ng-zorro-antd/grid'; +import { NzIconModule } from 'ng-zorro-antd/icon'; +import { NzInputModule } from 'ng-zorro-antd/input'; +import { NzSpinModule } from 'ng-zorro-antd/spin'; + +import { LayoutMarketComponent } from './market/market.component'; +import { LayoutBlankComponent } from './blank/blank.component'; + +const COMPONENTS = [LayoutBlankComponent]; + +const MARKET = [LayoutMarketComponent]; + +import { NzModalModule } from 'ng-zorro-antd/modal'; +import { NzTagModule } from 'ng-zorro-antd/tag'; +import { NzDividerModule } from 'ng-zorro-antd/divider'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + RouterModule, + AlainThemeModule.forChild(), + ThemeBtnModule, + SettingDrawerModule, + LayoutDefaultModule, + NoticeIconModule, + GlobalFooterModule, + NzDropDownModule, + NzInputModule, + NzAutocompleteModule, + NzGridModule, + NzFormModule, + NzSpinModule, + NzBadgeModule, + NzAvatarModule, + NzIconModule, + NzModalModule, + NzTagModule, + NzDividerModule, + RouterModule, + MARKET + ], + declarations: [...COMPONENTS], + exports: [...COMPONENTS, ...MARKET,RouterModule] +}) +export class LayoutModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.html new file mode 100644 index 00000000000..81c1999c3ea --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.html @@ -0,0 +1,227 @@ + + + + + + + Title + + +
+
+
+
+
+
+ + Welcome to HertzBeat 监控模版市场! +
+
+
+
+ 目前共有{{ count }}个模版 + 搜索! +
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+ + +
+ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.ts new file mode 100644 index 00000000000..4170e2ca02f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/layout/market/market.component.ts @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnInit} from '@angular/core'; +import {LayoutDefaultOptions} from '@delon/theme/layout-default'; +import {RouterOutlet} from "@angular/router"; +import {NzImageDirective} from "ng-zorro-antd/image"; +import {TemplateService} from "../../service/template.service"; +import {NzMessageService} from "ng-zorro-antd/message"; +import {NgIf} from "@angular/common"; +import {LocalStorageService} from "../../service/local-storage.service"; +import {DataService} from "../../service/data.service"; + +@Component({ + selector: 'app-market', + templateUrl: 'market.component.html', + standalone: true, + imports: [ + RouterOutlet, + NzImageDirective, + NgIf + ] +}) +export class LayoutMarketComponent implements OnInit{ + options: LayoutDefaultOptions = { + logoExpanded: `./assets/brand_white.svg`, + logoCollapsed: `./assets/logo.svg` + }; + constructor(private templateService: TemplateService, + private msg: NzMessageService, + private localStorageService: LocalStorageService, + private dataService: DataService + ) {} + + count=0; + isLogin:boolean = false; + + ngOnInit(): void { + this.dataService.isLoginMsg.subscribe(isLogin => this.isLogin = isLogin) + const userInfo = this.localStorageService.getData('userInfo'); + if(userInfo!=null){ + this.isLogin=true + } + + this.templateService.getTemplateCount(0,0).subscribe(message=>{ + if (message.code == 0) { + this.count=message.data; + }else{ + this.msg.error(message.error) + } + }) + } + + logout():void{ + this.localStorageService.removeData('userInfo'); + this.localStorageService.removeData('userId'); + this.localStorageService.removeData('Authorization'); + this.localStorageService.removeData('refresh-token'); + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/pojo/Message.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/pojo/Message.ts new file mode 100644 index 00000000000..82a95cb0eb9 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/pojo/Message.ts @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 class Message { + data!: T; + msg!: string; + code: number = 0; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.html new file mode 100644 index 00000000000..cad46c4bbf6 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.html @@ -0,0 +1,125 @@ + + +
+
+
+
+
+
+
+
+ HertzBeat +

+ 监控模版市场 + + + + +

+
+
+

易用友好的开源实时监控系统
快来上传、浏览、下载模版吧!

+ 开始浏览 + + + + + + + + + + + + +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+

开箱即用

+

集监控-告警-通知为一体,支持应用服务,Web,数据库,缓存,操作系统,中间件,大数据,云原生,网络等监控阈值告警; + 易用友好,无需Agent,全WEB页面操作

+
+
+
+
+
+
+ + + +
+
+

高性能与自定义

+

将 Http,Jmx,Ssh,Snmp,Jdbc 等协议规范可配置模版化,只需在线配置YML就可自定义监控指标; 自由的告警阈值规则,消息及时送达

+
+
+
+
+
+
+ + + +
+
+

拥抱开源

+

Apache HertzBeat (incubating) 的单机集群版全开源,基于 Apache2.0 License; 欢迎任何对此有兴趣的同学参与其中

+
+
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.less new file mode 100644 index 00000000000..a76e698074b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.less @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +.image-container { + display: flex; + justify-content: center; + align-items: center; + position: relative; + width: 300px; + height: 300px; + margin: auto; +} + +.img1, .img2 { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.img2 { + opacity: 0.7; +} + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.ts new file mode 100644 index 00000000000..f8fd8c7162f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/home-page/home-page.component.ts @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, Component, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {window} from "rxjs"; + +@Component({ + selector: 'home-page', + templateUrl: './home-page.component.html', + styleUrls: ['./home-page.component.less'], + standalone: true, + providers: [], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class HomePageComponent implements OnInit,OnDestroy { + constructor( + fb: FormBuilder, + ) { + this.form = fb.group({ + userName: [null, [Validators.required]], + password: [null, [Validators.required]], + mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]], + captcha: [null, [Validators.required]], + remember: [true] + }); + } + + count=0; + + form: FormGroup; + error = ''; + type = 0; + loading = false; + + interval$: any; + + ngOnInit(): void { + } + + ngOnDestroy(): void { + if (this.interval$) { + clearInterval(this.interval$); + } + } + + protected readonly window = window; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.html new file mode 100644 index 00000000000..e290ad1f77a --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.html @@ -0,0 +1,66 @@ + + +
+
+
+
+
+
+
+
邮箱登录
+ + +
+
+
+
+
+ + +
+
+
+
+ + + 忘记密码? +
+
+
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.less new file mode 100644 index 00000000000..f284cbbade4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.less @@ -0,0 +1,18 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.ts new file mode 100644 index 00000000000..d27e2b74b4f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/login/login.component.ts @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, Injector, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder, FormsModule} from '@angular/forms'; +import {AuthService, LoginDTO} from "../../service/auth.service"; +import {LocalStorageService} from "../../service/local-storage.service"; +import {NzMessageService} from "ng-zorro-antd/message"; +import {Router} from "@angular/router"; +import {NzButtonComponent} from "ng-zorro-antd/button"; +import {DataService} from "../../service/data.service"; + +@Component({ + selector: 'login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.less'], + standalone: true, + providers: [], + imports: [ + NzButtonComponent, + FormsModule + ], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class LoginComponent implements OnInit,OnDestroy { + constructor( + fb: FormBuilder, + private authService: AuthService, + private localStorageService: LocalStorageService, + private msg: NzMessageService, + private injector: Injector, + private dataService: DataService, + ) {} + + loginForm: LoginDTO={ + type:1, + identifier:'', + credential:'', + }; + + submitLogin():void{ + console.log(this.loginForm) + this.authService.tryLogin(this.loginForm).subscribe(response => { + if(response.code == 0) { + console.log(response); + this.localStorageService.storageAuthorizationToken(response.data.token); + this.localStorageService.storageRefreshToken(response.data.refreshToken); + this.msg.success('登录成功'); + this.localStorageService.putData('userInfo',this.loginForm.identifier); + this.localStorageService.putData('userId',response.data.id); + this.dataService.sendLoginMsg(true); + window.history.back(); + }else{ + this.msg.error('登录失败:'+response.msg) + } + }) + } + + ngOnInit(): void { + } + + ngOnDestroy(): void { + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market-routing.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market-routing.module.ts new file mode 100644 index 00000000000..bfe1c49810b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market-routing.module.ts @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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'; + +import { TemplateDetailComponent } from './template-detail/template-detail.component'; +import { TemplateListComponent } from './template-list/template-list.component'; + +const routes: Routes = [ + { path: '', component: TemplateListComponent }, + { path: 'list', component: TemplateListComponent }, + { path: 'detail', component: TemplateDetailComponent }, + { path: '**', component: TemplateListComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class MarketRoutingModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market.module.ts new file mode 100644 index 00000000000..375be92dfde --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/market.module.ts @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {ClipboardModule} from '@angular/cdk/clipboard'; +import {NgModule, Type} from '@angular/core'; +import {NzBreadCrumbModule} from 'ng-zorro-antd/breadcrumb'; +import {NzLayoutModule} from 'ng-zorro-antd/layout'; +import {NzRadioModule} from 'ng-zorro-antd/radio'; +import {NzSpaceModule} from 'ng-zorro-antd/space'; +import {NzSwitchModule} from 'ng-zorro-antd/switch'; + +import {MarketRoutingModule} from './market-routing.module'; +import {TemplateDetailComponent} from './template-detail/template-detail.component'; +import {TemplateListComponent} from './template-list/template-list.component'; +import {NzInputDirective, NzInputGroupComponent} from "ng-zorro-antd/input"; +import {NzOptionComponent, NzSelectModule} from "ng-zorro-antd/select"; +import {NzButtonComponent} from "ng-zorro-antd/button"; +import {RouterModule} from "@angular/router"; +import {CommonModule} from "@angular/common"; +import {FormsModule} from "@angular/forms"; +import {NzPaginationComponent} from "ng-zorro-antd/pagination"; +import {NzCheckboxComponent, NzCheckboxGroupComponent} from "ng-zorro-antd/checkbox"; +import {NzIconDirective} from "ng-zorro-antd/icon"; +import {NzTooltipDirective} from "ng-zorro-antd/tooltip"; +import {NzCardComponent, NzCardMetaComponent} from "ng-zorro-antd/card"; +import {NzAvatarComponent} from "ng-zorro-antd/avatar"; + +const COMPONENTS: Array> = [TemplateListComponent, TemplateDetailComponent, TemplateListComponent]; + +@NgModule({ + imports: [ + MarketRoutingModule, + NzBreadCrumbModule, + NzSwitchModule, + NzRadioModule, + NzLayoutModule, + NzSpaceModule, + ClipboardModule, + NzInputGroupComponent, + NzOptionComponent, + NzButtonComponent, + NzInputDirective, + CommonModule, + FormsModule, + NzSelectModule, + NzPaginationComponent, + NzCheckboxComponent, + NzCheckboxGroupComponent, + NzIconDirective, + NzTooltipDirective, + NzCardComponent, + NzCardMetaComponent, + NzAvatarComponent + ], + declarations: COMPONENTS, + exports:[RouterModule] +}) +export class MarketModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.html new file mode 100644 index 00000000000..d45c2feaacc --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.html @@ -0,0 +1,277 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 模版 + + + + + 详情 +

+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+ +
+
+

{{ (templateInfo!=null)?templateInfo.name:'xxx' }}

+
+
+
+ +  {{ templateInfo.star }} +
+ +  200 +
+
+ +  {{ templateInfo.download>=1000?((templateInfo.download/1000).toFixed(2)+'k'):templateInfo.download }} +
+
+
+
+
    +
  • 类别 :  {{ categoryStr }}
  • +
  • 标签 :  MySQL
  • +
  • 最新版本 :  {{ latestVersion?latestVersion.version:'xxx' }}
  • +
  • 最后更新时间 :  {{ templateInfo.updateTime }}
  • +
+ +
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ 概要信息 : +

{{ templateInfo.description }}

+ +
+
+ 详细信息 : + +

。。。。。

+
+
+ 其他信息 : +
    +
  • + + + + + +

    {{ templateInfo.description }}

    +
  • +
  • + + + + + +

    {{ templateInfo.description }}

    +
  • +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
版本号概要更新时间下载量下载分享链接
{{ item.version }} {{ item.description }} {{ item.createTime }} {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }} + download + share
+
+
+ +
+
+
+
+
+
+
+
+

+ +

+
+
就这么用
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.less new file mode 100644 index 00000000000..042f3ce1f39 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.less @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.ts new file mode 100644 index 00000000000..27f23efcdfe --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-detail/template-detail.component.ts @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {saveAs} from 'file-saver'; +import {NzMessageService} from 'ng-zorro-antd/message'; + +import {TemplateService} from '../../../service/template.service'; +import {window} from "rxjs"; +import {LocalStorageService} from "../../../service/local-storage.service"; +import {StarService} from "../../../service/star.service"; +import {VersionService} from "../../../service/version.service"; + +@Component({ + selector: 'market', + templateUrl: './template-detail.component.html', + styleUrls: ['./template-detail.component.less'] +}) +export class TemplateDetailComponent implements OnInit, OnDestroy { + constructor(private templateService: TemplateService, + private msg: NzMessageService, + private localStorageService: LocalStorageService, + private starService: StarService, + private versionService: VersionService,) {} + + userId:number = 0; + + templateInfo :any = null; + categoryList: any[] = []; + latestVersion :any = null; + versionList: any[] = []; + + totalElements = 10; + totalPages = 1; + pageIndex=0; + pageSize = 2; + numberOfPages = 1; + newPageIndex=this.pageIndex; + newPageSize = this.pageSize; + pageSizeOptions:number[]=[2,5,10,20]; + + categoryStr=''; + + isStarNow:boolean = false; + + showPage = 1; + + downloadTemplateNow(): void { + this.templateService.downloadLatestTemplate(this.templateInfo.user, this.templateInfo.id, this.templateInfo.latest).subscribe(blob => { + saveAs(blob, `${this.templateInfo.name}-${this.latestVersion.version}.yml`); + this.localStorageService.removeData('nowTemplate'); + this.templateInfo.download++; + for (let item of this.versionList) { + if(item.id==this.templateInfo.latest) { + item.download++; + break; + } + } + this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo)); + }); + } + + downloadVersion(version:string, versionId:number): void { + this.templateService.downloadTemplate(this.templateInfo.user, this.templateInfo.id,version, versionId).subscribe(blob => { + saveAs(blob, `${this.templateInfo.name}-${version}.yml`); + for (let item of this.versionList) { + if(item.id==versionId) { + item.download++; + break; + } + } + this.localStorageService.removeData('nowTemplate'); + this.templateInfo.download++; + this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo)); + }); + } + + shareVersionNow(versionId:number): void { + this.versionService.shareVersion(versionId).subscribe(message=>{ + if(message.code==0){ + this.msg.success('已复制分享链接,快去发送给对方吧!'); + const selBox = document.createElement('textarea'); + selBox.style.position = 'fixed'; + selBox.style.left = '0'; + selBox.style.top = '0'; + selBox.style.opacity = '0'; + selBox.value = message.msg; + document.body.appendChild(selBox); + selBox.focus(); + selBox.select(); + document.execCommand('copy'); + document.body.removeChild(selBox); + }else{ + this.msg.error(message.msg); + } + }) + } + + ngOnInit(): void { + const user=this.localStorageService.getData("userId"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + + this.templateInfo=JSON.parse(this.localStorageService.getData('nowTemplate')); + if(this.userId!=0){ + this.starService.assertTemplateStarByUser(this.userId,this.templateInfo.id).subscribe(response => { + if(response.code == 0) { + this.isStarNow=response.data + }else{ + this.msg.error('是否收藏判断失败'+response.msg) + } + }) + } + this.versionService.getVersion(this.templateInfo.latest).subscribe(response => { + if(response.code == 0) { + this.latestVersion=response.data; + console.log(this.latestVersion); + }else { + this.msg.error('版本信息获取失败'+response.msg) + } + }) + this.categoryList=JSON.parse(this.localStorageService.getData('categoryList')); + console.log(this.templateInfo); + console.log(this.categoryList); + for (const item of this.categoryList) { + if(item.value==this.templateInfo.categoryId){ + this.categoryStr=item.label; + } + } + this.getVersions(); + } + + pageIndexChange(newIndex:number){ + this.newPageIndex=newIndex-1; + console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize); + this.getVersions() + } + + pageSizeChange(newSize:number){ + this.newPageSize=newSize; + console.log("newSize",newSize,"newPageIndex",this.newPageIndex); + this.getVersions() + } + + getVersions(){ + this.versionService.getVersionPage(this.templateInfo.id,0,this.newPageIndex,this.newPageSize).subscribe(response => { + if(response.code == 0) { + this.versionList=response.data.content; + this.totalElements=response.data.totalElements; + this.totalPages=response.data.totalPages; + this.pageIndex=response.data.pageable.pageNumber; + this.pageSize=response.data.pageable.pageSize; + this.numberOfPages=response.data.numberOfElements; + } + }) + } + + starTemplate(id:number){ + const formData = new FormData(); + formData.append('user', this.userId.toString()); + formData.append('template', id.toString()); + this.starService.starTemplate(formData) + .subscribe(message=>{ + if (message.code == 0) { + this.msg.success(message.msg); + this.isStarNow=true; + this.templateInfo.star++; + }else{ + this.msg.error(message.msg); + } + }) + } + + cancelStarTemplate(id:number){ + const formData = new FormData(); + formData.append('templateId', id.toString()); + this.starService.cancelStarTemplate(this.userId,formData) + .subscribe(message=>{ + if (message.code == 0) { + this.msg.success(message.msg); + this.isStarNow=false; + this.templateInfo.star--; + }else{ + this.msg.error(message.msg); + } + }) + } + + ngOnDestroy(): void { + this.localStorageService.removeData('nowTemplate'); + } + + protected readonly window = window; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.html new file mode 100644 index 00000000000..18037cb0672 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.html @@ -0,0 +1,229 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 监 控 模 版 + + + + + 市 场 +

+
+
+
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + +
+
+
+
+ + + + + + +
+
+
+
+
+
+
+ +
+

+ 模版类别 +

+
+
+
+ + +
+
+
+
+

标签

+
+
+
+ Docker + Linux + K8S + SpringBoot2 + SpringBoot3 + Web + Windows +
+
+
+
+
+
+
+
+
+
+ + + + + + + +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }} +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.less new file mode 100644 index 00000000000..f5397f4f323 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.less @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +nz-select { + width: 352px; + //height: 60px; +} + +.material-symbols-outlined { + font-variation-settings: + 'FILL' 0, + 'wght' 400, + 'GRAD' 0, + 'opsz' 18 +} + +second-container { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 10px; +} + +/deep/ .ant-checkbox-group, .ant-collapse { + padding: 0; + line-height: 1.5715; + font-size: 17px; + color: rgba(0, 0, 0, .85); + box-sizing: border-box; + font-variant: tabular-nums; + font-feature-settings: 'tnum'; + list-style: none; +} + +/deep/ .ant-checkbox-wrapper { + display: inline-flex; + align-items: baseline; + line-height: unset; + cursor: pointer; + font-size: 17px; + font-family: "Gill Sans", sans-serif; + padding-bottom: 1rem; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.ts new file mode 100644 index 00000000000..6add0fa53b0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/market/template-list/template-list.component.ts @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {NzMessageService} from 'ng-zorro-antd/message'; + +import {TemplateService, TemplateVO} from '../../../service/template.service'; +import {CategoryService} from "../../../service/category.service"; +import {StarService} from "../../../service/star.service"; +import {LocalStorageService} from "../../../service/local-storage.service"; +import {saveAs} from "file-saver"; + +declare global { + interface Window { URL: any; } +} + +window.URL = window.URL || {}; + +@Component({ + selector: 'market', + templateUrl: './template-list.component.html', + styleUrls: ['./template-list.component.less'] +}) +export class TemplateListComponent implements OnInit, OnDestroy { + constructor(private templateService: TemplateService, + private msg: NzMessageService, + private categoryService: CategoryService, + private starService: StarService, + private localStorageService: LocalStorageService,) {} + + templateList: TemplateVO[] = []; + userId:number=0; + + totalElements = 1; + totalPages = 1; + pageIndex=0; + pageSize = 9; + numberOfPages = 1; + newPageIndex= this.pageIndex; + newPageSize = this.pageSize; + pageSizeOptions:number[]=[9,18,27]; + + nameLike=''; + type = 0; + + allChecked = false; + indeterminate = true; + checkCategory:number[] = [1]; + categoryList = [ + { label: '数据库监控模版', value: 1, checked: true }, + { label: '应用服务监控模版', value: 2, checked: false }, + ]; + + orderOption = 1; + + loading = false; + + ngOnInit(): void { + this.templateList=[]; + this.categoryService.clearCategoryList(); + this.categoryService.getAllCategoryByIsDel(0).subscribe(message => { + // console.log('返回结果',message); + if (message.code == 0) { + this.categoryService.addCategoryList(message.data) + this.categoryList=[]; + this.allChecked=true; + this.indeterminate=false; + this.categoryService.getCategoryList().forEach(item=>{ + this.checkCategory.push(item.id); + this.categoryList.push({label: item.description, value: item.id, checked:true}); + }) + this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList)); + }else{ + this.msg.error('类别请求失败:'+message.msg); + } + }) + + const user=this.localStorageService.getData("userId"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + + this.templateService.getTemplatePage(0, this.userId,0,9).subscribe(message => { + if (message.code == 0) { + this.templateList.push(...message.data.content); + console.log(this.templateList); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + // this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + } else { + this.msg.error(message.msg); + } + }); + } + + orderOptionChange(orderValue:number) { + this.msg.warning('排序功能开发中!'); + console.log(orderValue); + } + + tagChange(){ + this.msg.warning('标签功能开发中!'); + } + + pageIndexChange(newIndex:number){ + this.newPageIndex=newIndex-1; + // console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize); + this.getTemplatePageByOption() + } + + pageSizeChange(newSize:number){ + this.newPageSize=newSize; + // console.log("newSize",newSize,"newPageIndex",this.newPageIndex); + this.getTemplatePageByOption() + } + + getTemplatePageByOption(){ + this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize) + .subscribe(message => { + if (message.code == 0) { + this.templateList=[]; + this.templateList.push(...message.data.content); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + // this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + console.log(this.templateList) + console.log(message) + } else { + this.msg.error(message.msg); + } + }) + } + + updateAllChecked(): void { + this.checkCategory=[]; + this.indeterminate = false; + if (this.allChecked) { + this.categoryList = this.categoryList.map(item => ({ + ...item, + checked: true + })); + } else { + this.categoryList = this.categoryList.map(item => ({ + ...item, + checked: false + })); + } + this.categoryList.forEach(item => { + if (item.checked) { + this.checkCategory.push(item.value); + } + }) + if(this.checkCategory.length!=0) this.getTemplatePageByOption(); + } + + updateSingleChecked(): void { + this.checkCategory=[]; + if (this.categoryList.every(item => !item.checked)) { + this.allChecked = false; + this.indeterminate = false; + } else if (this.categoryList.every(item => item.checked)) { + this.allChecked = true; + this.indeterminate = false; + } else { + this.allChecked = false; + this.indeterminate = true; + } + this.categoryList.forEach(item => { + if (item.checked) { + this.checkCategory.push(item.value); + } + }) + this.getTemplatePageByOption(); + } + + downloadLatestTemplate(id:number,user:number,latest:number,name:string){ + this.templateService.downloadLatestTemplate(user,id,latest) + .subscribe((blob:Blob)=>{ + saveAs(blob, `${name}-latest.yml`); + for (let templateVO of this.templateList) { + if(templateVO.id==id) { + templateVO.download++; + break; + } + } + }, + error => { + console.error('下载文件时发生错误:', error); + }); + } + + pickTemplate(id:number){ + this.templateService.setNowTemplate(id); + let nowTemplate = this.templateService.getNowTemplate(); + localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate)); + // console.log(this.templateService.getNowTemplate()); + } + + starTemplate(id:number){ + const formData = new FormData(); + formData.append('user', this.userId.toString()); + formData.append('template', id.toString()); + this.starService.starTemplate(formData) + .subscribe(message=>{ + if (message.code == 0) { + for (let templateVO of this.templateList) { + if(templateVO.id==id) { + templateVO.starByNowUser=true; + templateVO.star++; + break; + } + } + this.msg.success(message.msg); + }else{ + this.msg.error(message.msg); + } + }) + } + + cancelStarTemplate(id:number){ + const formData = new FormData(); + formData.append('templateId', id.toString()); + this.starService.cancelStarTemplate(this.userId,formData) + .subscribe(message=>{ + if (message.code == 0) { + this.msg.success(message.msg); + for (let templateVO of this.templateList) { + if(templateVO.id==id) { + templateVO.starByNowUser=false; + templateVO.star--; + break; + } + } + }else{ + this.msg.error(message.msg); + } + }) + } + + ngOnDestroy(): void { + this.templateList=[]; + this.categoryList=[]; + this.templateService.clearTemplateSubject(); + this.categoryService.clearCategoryList(); + } + protected readonly event = event; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes-routing.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes-routing.module.ts new file mode 100644 index 00000000000..0487149a4dc --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes-routing.module.ts @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {Routes} from '@angular/router'; +import {LayoutMarketComponent} from '../layout/market/market.component'; +import {HomePageComponent} from './home-page/home-page.component'; +import {LoginComponent} from './login/login.component'; +import {SignUpComponent} from "./sign-up/sign-up.component"; + +export const routes: Routes = [ + { + path: '', + component: LayoutMarketComponent, + children: [ + { path: '', redirectTo: 'home-page', pathMatch: 'full' }, + { path: 'login', component: LoginComponent }, + { path: 'sign-up', component: SignUpComponent }, + { path: 'home-page', component: HomePageComponent }, + { path: 'market', loadChildren: () => import('./market/market.module').then(m => m.MarketModule) }, + { path: 'user-center', loadChildren: () => import('./user-center/user-center.module').then(m => m.UserCenterModule) } + ] + }, + { path: '**', redirectTo: 'exception/404' } +]; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes.module.ts new file mode 100644 index 00000000000..5ead66cfa43 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/routes.module.ts @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {NzCollapseModule} from 'ng-zorro-antd/collapse'; +import {NzDividerModule} from 'ng-zorro-antd/divider'; +import {NzListModule} from 'ng-zorro-antd/list'; +import {NzTagModule} from 'ng-zorro-antd/tag'; +import {NzTimelineModule} from 'ng-zorro-antd/timeline'; + +import {LayoutModule} from '../layout/layout.module'; +import {HomePageComponent} from './home-page/home-page.component'; +import {LoginComponent} from './login/login.component'; +import {RouterModule} from "@angular/router"; +import {NzMessageModule} from "ng-zorro-antd/message"; +import {BrowserModule} from "@angular/platform-browser"; +import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; +import {FormsModule} from "@angular/forms"; +import {SignUpComponent} from "./sign-up/sign-up.component"; + +const COMPONENTS: Array> = [ + HomePageComponent,LoginComponent,SignUpComponent +]; + +@NgModule({ + imports: [ + NzTagModule, + NzTimelineModule, + NzDividerModule, + LayoutModule, + NzCollapseModule, + NzListModule, + RouterModule, + COMPONENTS, + NzMessageModule, + BrowserModule, + BrowserAnimationsModule, + FormsModule + ], + exports:[RouterModule] +}) +export class RoutesModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.html new file mode 100644 index 00000000000..88e6ecf79a1 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.html @@ -0,0 +1,75 @@ + + +
+
+
+
+
+
+
+
注册
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+ +
+
+
+
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.less new file mode 100644 index 00000000000..f284cbbade4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.less @@ -0,0 +1,18 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.ts new file mode 100644 index 00000000000..2f7625236c5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/sign-up/sign-up.component.ts @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, Injector, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder, FormsModule} from '@angular/forms'; +import {AuthService, LoginDTO, SignUpDTO} from "../../service/auth.service"; +import {LocalStorageService} from "../../service/local-storage.service"; +import {NzMessageService} from "ng-zorro-antd/message"; +import {Router} from "@angular/router"; +import {NzButtonComponent} from "ng-zorro-antd/button"; +import {DataService} from "../../service/data.service"; + +@Component({ + selector: 'login', + templateUrl: './sign-up.component.html', + styleUrls: ['./sign-up.component.less'], + standalone: true, + providers: [], + imports: [ + NzButtonComponent, + FormsModule + ], + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SignUpComponent implements OnInit,OnDestroy { + constructor( + fb: FormBuilder, + private authService: AuthService, + private localStorageService: LocalStorageService, + private msg: NzMessageService, + private injector: Injector, + private dataService: DataService, + ) {} + + SignUpForm: SignUpDTO={ + name:'', + email:'', + password:'', + }; + + passwordOk:string=''; + + submitSignUp():void{ + // console.log(this.SignUpForm) + if(this.passwordOk!=this.SignUpForm.password) this.msg.error('密码不一致'); + if(this.SignUpForm.email==null||this.SignUpForm.name==null||this.SignUpForm.password==null) this.msg.error('信息不全'); + this.authService.register(this.SignUpForm).subscribe(response => { + console.log(response); + if(response.code == 0) { + this.msg.success('注册成功'); + // window.history.back(); + }else{ + this.msg.error('注册失败:'+response.msg) + } + }) + } + + ngOnInit(): void { + } + + ngOnDestroy(): void { + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.html new file mode 100644 index 00000000000..285b7a3f63c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.html @@ -0,0 +1,349 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 模版 + + + + + + + + + + + + + + 详情 +

+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+ +
+
+

{{ templateInfo.name }}

+
+
+
+ +  {{ templateInfo.star }} +
+ +  200 +
+
+ +  {{ templateInfo.download>=1000?((templateInfo.download/1000).toFixed(2)+'k'):templateInfo.download }} +
+
+
+
+
    +
  • 类别 :  {{ categoryStr }}
  • +
  • 标签 :  MySQL
  • +
  • 最新版本 :  {{ latestVersion?latestVersion.version:'xxx' }}
  • +
  • 最后更新时间 :  {{ templateInfo.updateTime }}
  • +
+ +
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ 概要信息 : +

{{ templateInfo.description }}

+ +
+
+ 详细信息 : + +

。。。。。

+
+
+ 其他信息 : +
    +
  • + + + + + +

    {{ templateInfo.description }}

    +
  • +
  • + + + + + +

    {{ templateInfo.description }}

    +
  • +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
版本号概要更新时间下载量下载分享链接
{{ item.version }} {{ item.description }} {{ item.createTime }} {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }} + download + share
+
+
+ +
+
+
+
+
+
+
+
+

+ +

+
+
就这么用
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ + 版本号 + + + + + + 版本描述 + + + + + + 版本文件 + + +

+ +

+

点击该区域上传文件

+
+
+
+
+ + +
+ + +
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.less new file mode 100644 index 00000000000..042f3ce1f39 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.less @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.ts new file mode 100644 index 00000000000..8a88605fb19 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/assets-detail/assets-detail.component.ts @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {saveAs} from 'file-saver'; +import {NzMessageService} from 'ng-zorro-antd/message'; + +import {TemplateService} from '../../../service/template.service'; +import {finalize, Observable, Subscription, window} from "rxjs"; +import {LocalStorageService} from "../../../service/local-storage.service"; +import {CategoryService} from "../../../service/category.service"; +import {VersionService} from "../../../service/version.service"; +import {NzUploadChangeParam, NzUploadFile} from "ng-zorro-antd/upload"; + +interface TemplateInfo { + id: number; + name: string; + description: string; + descriptionVersion: string; + latest: number; + versions: string[]; + currentVersion: string; + user: string; + userId: number; + category: string; + categoryId: number; + download: number; + star:number; + create_time: string; + update_time: string; + off_shelf: number; + is_del: number; +} + +@Component({ + selector: 'market', + templateUrl: './assets-detail.component.html', + styleUrls: ['./assets-detail.component.less'] +}) +export class AssetsDetailComponent implements OnInit, OnDestroy { + constructor(private templateService: TemplateService, + private msg: NzMessageService, + private localStorageService: LocalStorageService, + private categoryService: CategoryService, + private versionService: VersionService,) {} + + userId:number=0; + + templateInfo :any = null; + categoryList: any[] = []; + latestVersion :any = null; + versionList: any[] = []; + + totalElements = 10; + totalPages = 1; + pageIndex=0; + pageSize = 2; + numberOfPages = 1; + newPageIndex=this.pageIndex; + newPageSize = this.pageSize; + pageSizeOptions:number[]=[2,5,10,20]; + + categoryStr=''; + + showPage = 1; + + visible = false; + + error = 'success'; + type = 0; + loading = false; + + count = 0; + interval$: any; + + fileList: NzUploadFile[] = []; + file: any[] = []; + + newTemplateInfo = { + id: 0, + name: '', + description: '模版描述', + descriptionVersion: '版本描述', + latest: 0, + currentVersion: 'v1.0.0', + user: 'user', + userId: 1, + category: '', + categoryId: 0, + download: 0, + star:0, + create_time: '2024', + update_time: '2024', + off_shelf: 0, + is_del: 0 + } as TemplateInfo; + + open(): void { + this.visible = true; + } + + close(): void { + this.visible = false; + } + + handleChange(info: NzUploadChangeParam) { + if (info.file.status !== 'uploading') { + console.log(info.file, info.fileList); + + const isLt4M = info.file.size! / 1024 / 1024 < 4; + if (!isLt4M) { + // this.message.error('Message.File.SizeFile'); + console.log('error:文件超过4M'); + } + // this.file = this.file.concat(info.file); + } + if (info.file.status === 'done') { + this.file.pop(); + // this.msg.success(`${info.file.name} file uploaded successfully`); + } else if (info.file.status === 'error') { + // this.msg.error(`${info.file.name} file upload failed.`); + } + } + + beforeUpload = (file: any) => { + while (this.file.length > 0) { + this.file.pop(); + } + console.log('beforeUpload', file); + this.file.push(file); + console.log('afterUpload', this.file); + return false; + }; + + getCategoryStr(value:number):string{ + for (const item of this.categoryList) { + if(item.value==value){ + return item.label; + } + } + return ' ' + } + + updateTemplate(): void { + if(this.file.length==0){ + this.msg.error("文件为空"); + return; + } + const formData = new FormData(); + if (this.file.length > 0) { + formData.append('file', this.file[0]); + this.newTemplateInfo.id=this.templateInfo.id; + this.newTemplateInfo.name=this.templateInfo.name; + this.newTemplateInfo.description=this.templateInfo.description; + this.newTemplateInfo.userId=this.templateInfo.user; + this.newTemplateInfo.categoryId=this.templateInfo.categoryId; + this.newTemplateInfo.category=this.getCategoryStr(this.newTemplateInfo.categoryId) + formData.append('templateDto', JSON.stringify(this.newTemplateInfo)); + const uploadTemplateRes$ = this.templateService + .upload(formData) + .pipe( + finalize(() => { + uploadTemplateRes$.unsubscribe(); + // this.tableLoading = false; + }) + ) + .subscribe( + message => { + console.log('message', message); + if (message.code === 0) { + // this.notifySvc.success(this.i18nSvc.fanyi('common.notify.edit-success'), ''); + this.msg.success(`模版文件上传成功`); + this.getVersions(); + this.close(); + } else { + this.msg.error(`模版上传失败:${message.msg}`); + // this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), message.msg); + } + // this.loadAlertConvergeTable(); + // this.tableLoading = false; + }, + error => { + console.log('err', error); + // this.tableLoading = false; + // this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), error.msg); + this.msg.error(`模版上传失败`, error.msg); + } + ); + } + } + + downloadTemplateNow(): void { + this.templateService.downloadLatestTemplate(this.templateInfo.user, this.templateInfo.id, this.templateInfo.latest).subscribe(blob => { + saveAs(blob, `${this.templateInfo.name}-${this.latestVersion.version}.yml`); + this.localStorageService.removeData('nowTemplate'); + this.templateInfo.download++; + this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo)); + }); + } + + downloadVersion(version:string, versionId:number): void { + this.templateService.downloadTemplate(this.templateInfo.user, this.templateInfo.id,version, versionId).subscribe(blob => { + saveAs(blob, `${this.templateInfo.name}-${version}.yml`); + this.localStorageService.removeData('nowTemplate'); + this.templateInfo.download++; + this.localStorageService.putData('nowTemplate', JSON.stringify(this.templateInfo)); + }); + } + + shareVersionNow(versionId:number): void { + this.versionService.shareVersion(versionId).subscribe(message=>{ + if(message.code==0){ + this.msg.success('已复制分享链接,快去发送给对方吧!'); + const selBox = document.createElement('textarea'); + selBox.style.position = 'fixed'; + selBox.style.left = '0'; + selBox.style.top = '0'; + selBox.style.opacity = '0'; + selBox.value = message.msg; + document.body.appendChild(selBox); + selBox.focus(); + selBox.select(); + document.execCommand('copy'); + document.body.removeChild(selBox); + }else{ + this.msg.error(message.msg); + } + }) + } + + ngOnInit(): void { + const user=this.localStorageService.getData("userId"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + + this.templateInfo=JSON.parse(this.localStorageService.getData('nowTemplate')); + this.versionService.getVersion(this.templateInfo.latest).subscribe(response => { + if(response.code == 0) { + this.latestVersion=response.data; + console.log(this.latestVersion); + }else { + this.msg.error('版本信息获取失败'+response.msg) + } + }) + this.categoryList=JSON.parse(this.localStorageService.getData('categoryList')); + // console.log(this.templateInfo); + // console.log(this.categoryList); + for (const item of this.categoryList) { + if(item.value==this.templateInfo.categoryId){ + this.categoryStr=item.label; + } + } + this.getVersions(); + } + + pageIndexChange(newIndex:number){ + this.newPageIndex=newIndex-1; + console.log("newPageIndex",this.newPageIndex,"newPageSize",this.newPageSize); + this.getVersions() + } + + pageSizeChange(newSize:number){ + this.newPageSize=newSize; + console.log("newSize",newSize,"newPageIndex",this.newPageIndex); + this.getVersions() + } + + getVersions(){ + this.versionService.getVersionPage(this.templateInfo.id,0,this.newPageIndex,this.newPageSize).subscribe(response => { + if(response.code == 0) { + this.versionList=response.data.content; + this.totalElements=response.data.totalElements; + this.totalPages=response.data.totalPages; + this.pageIndex=response.data.pageable.pageNumber; + this.pageSize=response.data.pageable.pageSize; + this.numberOfPages=response.data.numberOfElements; + } + }) + } + + ngOnDestroy(): void { + this.localStorageService.removeData('nowTemplate'); + } + + protected readonly window = window; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.html new file mode 100644 index 00000000000..233b0d53c1e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.html @@ -0,0 +1,192 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 个人 + + + + + + + + + + + + + + 中心 +

+
+
+
+
+
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + + + + + + +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }} +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.less new file mode 100644 index 00000000000..042f3ce1f39 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.less @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.ts new file mode 100644 index 00000000000..92adeaa0cd7 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-assets/user-assets.component.ts @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {NzMessageService} from 'ng-zorro-antd/message'; +import {NzUploadChangeParam, NzUploadFile} from 'ng-zorro-antd/upload'; +import {finalize, window} from 'rxjs'; + +import {TemplateService} from '../../../service/template.service'; + +import {CategoryService} from "../../../service/category.service"; +import {LocalStorageService} from "../../../service/local-storage.service"; +import {saveAs} from "file-saver"; + +interface TemplateInfo { + id: number; + name: string; + description: string; + descriptionVersion: string; + latest: number; + versions: string[]; + currentVersion: string; + user: string; + userId: number; + category: string; + categoryId: number; + download: number; + star:number, + create_time: string; + update_time: string; + off_shelf: number; + is_del: number; +} + +@Component({ + selector: 'user-upload', + templateUrl: './user-assets.component.html', + styleUrls: ['./user-assets.component.less'], +}) +export class UserAssetsComponent implements OnInit,OnDestroy { + constructor(fb: FormBuilder, + private templateService: TemplateService, + private msg: NzMessageService, + private categoryService: CategoryService, + private localStorageService: LocalStorageService,) {} + + userId:number=0; + + templateList: any[] = []; + + totalElements = 1; + totalPages = 1; + pageIndex=0; + pageSize = 9; + numberOfPages = 1; + newPageIndex=this.pageIndex; + newPageSize = this.pageSize; + pageSizeOptions:number[]=[9,18,27]; + + nameLike=''; + type = 0; + + allChecked = false; + indeterminate = true; + checkCategory:number[] = [1]; + categoryList = [ + { label: '数据库监控模版', value: 1, checked: true }, + { label: '应用服务监控模版', value: 2, checked: false }, + ]; + + orderOption = 1; + + loading = false; + + ngOnInit(): void { + const user=this.localStorageService.getData("userId"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + + // this.templateList=[]; + this.categoryService.clearCategoryList(); + this.categoryService.getAllCategoryByIsDel(0).subscribe(message => { + console.log('返回结果',message); + if (message.code == 0) { + this.categoryService.addCategoryList(message.data) + this.categoryList=[]; + this.allChecked=true; + this.indeterminate=false; + this.categoryService.getCategoryList().forEach(item=>{ + this.checkCategory.push(item.id); + this.categoryList.push({label: item.description, value: item.id, checked:true}); + }) + this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList)); + }else{ + this.msg.error('类别请求失败:'+message.msg); + } + }) + + this.templateService.getTemplatePageByUser(this.userId,0,this.pageSize).subscribe(message => { + if (message.code == 0) { + this.templateList.push(...message.data.content); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + } else { + this.msg.error(message.msg); + } + }); + } + + orderOptionChange(orderValue:number) { + // + console.log(orderValue); + } + + pageIndexChange(newIndex:number){ + this.newPageIndex=newIndex-1; + this.getTemplatePageByOption() + } + + pageSizeChange(newSize:number){ + this.newPageSize=newSize; + this.getTemplatePageByOption() + } + + getTemplatePageByOption(){ + this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize) + .subscribe(message => { + if (message.code == 0) { + this.templateList=[]; + this.templateList.push(...message.data.content); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + } else { + this.msg.error(message.msg); + } + }) + } + + updateAllChecked(): void { + this.checkCategory=[]; + this.indeterminate = false; + if (this.allChecked) { + this.categoryList = this.categoryList.map(item => ({ + ...item, + checked: true + })); + } else { + this.categoryList = this.categoryList.map(item => ({ + ...item, + checked: false + })); + } + this.categoryList.forEach(item => { + if (item.checked) { + this.checkCategory.push(item.value); + } + }) + } + + updateSingleChecked(): void { + this.checkCategory=[]; + if (this.categoryList.every(item => !item.checked)) { + this.allChecked = false; + this.indeterminate = false; + } else if (this.categoryList.every(item => item.checked)) { + this.allChecked = true; + this.indeterminate = false; + } else { + this.allChecked = false; + this.indeterminate = true; + } + this.categoryList.forEach(item => { + if (item.checked) { + this.checkCategory.push(item.value); + } + }) + } + + downloadLatestTemplate(id:number,user:number,latest:number,name:string){ + this.templateService.downloadLatestTemplate(user,id,latest) + .subscribe((blob:Blob)=>{ + saveAs(blob, `${name}-latest.yml`); + }, + error => { + console.error('下载文件时发生错误:', error); + }); + } + + pickTemplate(id:number){ + this.templateService.setNowTemplate(id); + let nowTemplate = this.templateService.getNowTemplate(); + localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate)); + // console.log(this.templateService.getNowTemplate()); + } + + ngOnDestroy(): void { + this.templateList=[]; + this.categoryList=[]; + this.templateService.clearTemplateSubject(); + this.categoryService.clearCategoryList(); + } + + protected readonly window = window; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center-routing.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center-routing.module.ts new file mode 100644 index 00000000000..6ad377039dc --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center-routing.module.ts @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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'; + +import { UserUploadComponent } from './user-upload/user-upload.component'; +import {UserAssetsComponent} from "./user-assets/user-assets.component"; +import {AssetsDetailComponent} from "./assets-detail/assets-detail.component"; +import {UserStarComponent} from "./user-star/user-star.component"; + +const routes: Routes = [ + { path: '', component: UserUploadComponent }, + { path: 'upload', component: UserUploadComponent }, + { path: 'assets', component: UserAssetsComponent }, + { path: 'detail', component: AssetsDetailComponent }, + { path: 'star', component: UserStarComponent }, + { path: '**', component: UserUploadComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UserCenterRoutingModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center.module.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center.module.ts new file mode 100644 index 00000000000..7e1742115a8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-center.module.ts @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {NzDividerModule} from 'ng-zorro-antd/divider'; +import {NzUploadModule} from 'ng-zorro-antd/upload'; + +import {UserCenterRoutingModule} from './user-center-routing.module'; +import {UserUploadComponent} from './user-upload/user-upload.component'; +import {FormsModule} from "@angular/forms"; +import {CommonModule} from "@angular/common"; +import {NzOptionComponent, NzSelectComponent} from "ng-zorro-antd/select"; +import {NzAutosizeDirective, NzInputDirective, NzInputGroupComponent} from "ng-zorro-antd/input"; +import {NzFormControlComponent, NzFormDirective, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form"; +import {NzColDirective, NzRowDirective} from "ng-zorro-antd/grid"; +import {NzDatePickerComponent} from "ng-zorro-antd/date-picker"; +import {NzTimePickerComponent} from "ng-zorro-antd/time-picker"; +import {NzInputNumberComponent} from "ng-zorro-antd/input-number"; +import {NzIconDirective} from "ng-zorro-antd/icon"; +import {UserAssetsComponent} from "./user-assets/user-assets.component"; +import {NzPaginationComponent} from "ng-zorro-antd/pagination"; +import {AssetsDetailComponent} from "./assets-detail/assets-detail.component"; +import {NzDrawerComponent, NzDrawerContentDirective} from "ng-zorro-antd/drawer"; +import {NzButtonComponent} from "ng-zorro-antd/button"; +import {UserStarComponent} from "./user-star/user-star.component"; +import {NzTooltipDirective} from "ng-zorro-antd/tooltip"; +import {NzAvatarComponent} from "ng-zorro-antd/avatar"; +import {NzCardComponent, NzCardMetaComponent} from "ng-zorro-antd/card"; + +const COMPONENTS: Array> = [UserUploadComponent, UserAssetsComponent,AssetsDetailComponent,UserStarComponent]; + +@NgModule({ + + imports: [ + UserCenterRoutingModule, + NzDividerModule, + NzUploadModule, + FormsModule, + CommonModule, + NzOptionComponent, + NzSelectComponent, + NzAutosizeDirective, + NzInputDirective, + NzFormItemComponent, + NzFormLabelComponent, + NzFormControlComponent, + NzColDirective, + NzDatePickerComponent, + NzTimePickerComponent, + NzInputNumberComponent, + NzFormDirective, + NzIconDirective, + NzPaginationComponent, + NzDrawerComponent, + NzButtonComponent, + NzInputGroupComponent, + NzRowDirective, + NzDrawerContentDirective, + NzTooltipDirective, + NzAvatarComponent, + NzCardComponent, + NzCardMetaComponent, + ], + declarations: COMPONENTS, + providers:[...COMPONENTS], +}) +export class UserCenterModule {} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.html new file mode 100644 index 00000000000..464a437c533 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.html @@ -0,0 +1,208 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 个人 + + + + + + + + + + + + + + 中心 +

+
+
+
+
+
+ +
+
+
+
+ +
+ +
+
+
+
+
+ + + + + + + +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.star>=1000?((item.star/1000).toFixed(2)+'k'):item.star }} +
+
+ +
+  {{ item.download>=1000?((item.download/1000).toFixed(2)+'k'):item.download }} +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.less new file mode 100644 index 00000000000..042f3ce1f39 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.less @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.ts new file mode 100644 index 00000000000..a06d21b9330 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-star/user-star.component.ts @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {NzMessageService} from 'ng-zorro-antd/message'; + +import {TemplateService, TemplateVO} from '../../../service/template.service'; + +import {CategoryService} from "../../../service/category.service"; +import {StarService} from "../../../service/star.service"; +import {LocalStorageService} from "../../../service/local-storage.service"; +import {saveAs} from "file-saver"; + +// interface TemplateInfo { +// id: number; +// name: string; +// description: string; +// descriptionVersion: string; +// latest: number; +// versions: string[]; +// currentVersion: string; +// user: string; +// userId: number; +// category: string; +// categoryId: number; +// download: number; +// star:number, +// create_time: string; +// update_time: string; +// off_shelf: number; +// is_del: number; +// } + +@Component({ + selector: 'user-upload', + templateUrl: './user-star.component.html', + styleUrls: ['./user-star.component.less'], +}) +export class UserStarComponent implements OnInit,OnDestroy { + constructor(fb: FormBuilder, + private templateService: TemplateService, + private msg: NzMessageService, + private categoryService: CategoryService, + private starService: StarService, + private localStorageService: LocalStorageService,) {} + + userId:number=0; + + templateList: TemplateVO[] = []; + + totalElements = 1; + totalPages = 1; + pageIndex=0; + pageSize = 9; + numberOfPages = 1; + newPageIndex=this.pageIndex; + newPageSize = this.pageSize; + pageSizeOptions:number[]=[9,18,27]; + + nameLike=''; + type = 0; + + allChecked = false; + indeterminate = true; + checkCategory:number[] = [1]; + categoryList = [ + { label: '数据库监控模版', value: 1, checked: true }, + { label: '应用服务监控模版', value: 2, checked: false }, + ]; + + orderOption = 1; + + loading = false; + + ngOnInit(): void { + this.templateList=[] + const user=this.localStorageService.getData("userId"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + + this.categoryService.clearCategoryList(); + this.categoryService.getAllCategoryByIsDel(0).subscribe(message => { + console.log('返回结果',message); + if (message.code == 0) { + this.categoryService.addCategoryList(message.data) + this.categoryList=[]; + this.allChecked=true; + this.indeterminate=false; + this.categoryService.getCategoryList().forEach(item=>{ + this.checkCategory.push(item.id); + this.categoryList.push({label: item.description, value: item.id, checked:true}); + }) + this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList)); + }else{ + this.msg.error('类别请求失败:'+message.msg); + } + }) + + this.starService.getTemplatePageByUserStar(this.userId,0,9).subscribe(message => { + if (message.code == 0) { + this.templateList=message.data.content; + // this.templateList.push(...message.data.content); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + } else { + this.msg.error(message.msg); + } + }); + } + + pageIndexChange(newIndex:number){ + this.newPageIndex=newIndex-1; + this.getTemplatePageByOption() + } + + pageSizeChange(newSize:number){ + this.newPageSize=newSize; + this.getTemplatePageByOption() + } + + getTemplatePageByOption(){ + this.templateService.getTemplatePageByOption(this.userId,this.allChecked,this.checkCategory,this.nameLike,this.orderOption,0,this.newPageIndex,this.newPageSize) + .subscribe(message => { + if (message.code == 0) { + this.templateList=[]; + this.templateList.push(...message.data.content); + this.totalElements=message.data.totalElements; + this.totalPages=message.data.totalPages; + this.pageIndex=message.data.pageable.pageNumber; + this.pageSize=message.data.pageable.pageSize; + this.numberOfPages=message.data.numberOfElements; + this.msg.success('查询成功'); + this.templateService.setTemplateSubject(this.templateList); + } else { + this.msg.error(message.msg); + } + }) + } + + downloadLatestTemplate(id:number,user:number,latest:number,name:string){ + this.templateService.downloadLatestTemplate(user,id,latest) + .subscribe((blob:Blob)=>{ + saveAs(blob, `${name}-latest.yml`); + }, + error => { + console.error('下载文件时发生错误:', error); + }); + } + + pickTemplate(id:number){ + this.templateService.setNowTemplate(id); + let nowTemplate = this.templateService.getNowTemplate(); + localStorage.setItem('nowTemplate', JSON.stringify(nowTemplate)); + // console.log(this.templateService.getNowTemplate()); + } + + starTemplate(id:number){ + const formData = new FormData(); + formData.append('user', this.userId.toString()); + formData.append('template', id.toString()); + this.starService.starTemplate(formData) + .subscribe(message=>{ + if (message.code == 0) { + for (let templateVO of this.templateList) { + if(templateVO.id==id) { + templateVO.starByNowUser=true; + templateVO.star++; + break; + } + } + this.msg.success(message.msg); + }else{ + this.msg.error(message.msg); + } + }) + } + + cancelStarTemplate(id:number){ + const formData = new FormData(); + formData.append('templateId', id.toString()); + this.starService.cancelStarTemplate(1,formData) + .subscribe(message=>{ + if (message.code == 0) { + this.msg.success(message.msg); + for (let templateVO of this.templateList) { + if(templateVO.id==id) { + templateVO.starByNowUser=false; + templateVO.star--; + break; + } + } + }else{ + this.msg.error(message.msg); + } + }) + } + + ngOnDestroy(): void { + this.templateList=[]; + this.categoryList=[]; + this.templateService.clearTemplateSubject(); + this.categoryService.clearCategoryList(); + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.html b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.html new file mode 100644 index 00000000000..0b5409d7590 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.html @@ -0,0 +1,169 @@ + + +
+
+
+
+
+
+
+ Apache + . + HertzBeat +
+

+ 个人 + + + + + 中心 +

+
+
+
+
+
+ +
+
+
+
+ +
+ +
+
+
新建模版
+ 按照规定格式上传自定义模版吧! +
+ + 模版名称 + + + + + + 模版类别 + + + + + + + + 模版标签 + + + + + + 首版版本号 + + + + + + 模版描述 + + + + + + 首版描述 + + + + + + 首版文件 + + +

+ +

+

点击该区域上传文件

+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.less b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.less new file mode 100644 index 00000000000..042f3ce1f39 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.less @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.ts new file mode 100644 index 00000000000..0c40d8a2cea --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/routes/user-center/user-upload/user-upload.component.ts @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, OnDestroy, OnInit} from '@angular/core'; +import {FormBuilder} from '@angular/forms'; +import {NzMessageService} from 'ng-zorro-antd/message'; +import {NzUploadChangeParam, NzUploadFile} from 'ng-zorro-antd/upload'; +import {finalize, window} from 'rxjs'; + +import {TemplateService} from '../../../service/template.service'; + +import {CategoryService} from "../../../service/category.service"; +import {LocalStorageService} from "../../../service/local-storage.service"; + +interface TemplateInfo { + id: number; + name: string; + description: string; + descriptionVersion: string; + latest: number; + versions: string[]; + currentVersion: string; + user: string; + userId: number; + category: string; + categoryId: number; + download: number; + star:number, + create_time: string; + update_time: string; + off_shelf: number; + is_del: number; +} + +@Component({ + selector: 'user-upload', + templateUrl: './user-upload.component.html', + styleUrls: ['./user-upload.component.less'], +}) +export class UserUploadComponent implements OnInit,OnDestroy { + constructor(fb: FormBuilder, + private templateService: TemplateService, + private msg: NzMessageService, + private categoryService: CategoryService, + private localStorageService: LocalStorageService,) {} + + userId:number=0; + + error = 'success'; + type = 0; + loading = false; + + count = 0; + interval$: any; + + fileList: NzUploadFile[] = []; + file: any[] = []; + uniqueFile:any=null; + + templateInfo = { + id: 0, + name: '', + description: '模版描述', + descriptionVersion: '首版描述', + latest: 0, + currentVersion: 'v1.0.0', + user: 'user', + userId: 1, + category: '', + categoryId: 0, + download: 0, + star:0, + create_time: '2024', + update_time: '2024', + off_shelf: 0, + is_del: 0 + } as TemplateInfo; + + categoryList = [ + { label: '数据库监控模版', value: 1, checked: true }, + { label: '应用服务监控模版', value: 2, checked: false }, + ]; + + ngOnInit(): void { + const user=this.localStorageService.getData("userId"); + const userName=this.localStorageService.getData("userInfo"); + if(user==null) this.userId=0; + else this.userId=parseInt(user); + this.templateInfo.userId=this.userId; + this.templateInfo.user=userName==null?'user':userName; + + this.categoryList=[]; + this.categoryService.clearCategoryList(); + this.categoryService.getAllCategoryByIsDel(0).subscribe(message => { + if (message.code == 0) { + for (const item of message.data) { + this.categoryList.push({label: item.description, value: item.id, checked:true}); + } + this.localStorageService.putData('categoryList',JSON.stringify(this.categoryList)); + }else{ + this.msg.error('类别请求失败:'+message.msg); + } + }) + } + + getCategoryStr(value:number):string{ + for (const item of this.categoryList) { + if(item.value==value){ + return item.label; + } + } + return ' ' + } + + ngOnDestroy(): void { + if (this.interval$) { + clearInterval(this.interval$); + } + } + + handleChange(info: NzUploadChangeParam) { + if (info.file.status !== 'uploading') { + const isLt4M = info.file.size! / 1024 / 1024 < 4; + if (!isLt4M) { + // this.message.error('Message.File.SizeFile'); + console.log('error:文件超过4M'); + } + // this.file = this.file.concat(info.file); + } + if (info.file.status === 'done') { + this.file.pop(); + this.fileList.reverse() + if(this.fileList.length > 1) { + this.fileList.pop() + } + // this.msg.success(`${info.file.name} file uploaded successfully`); + } else if (info.file.status === 'error') { + this.fileList=[]; + // this.msg.error(`${info.file.name} file upload failed.`); + } + } + + beforeUpload = (file: any) => { + this.file.push(file); + this.uniqueFile=file; + this.fileList=[] + return true; + }; + + uploadTemplate(): void { + console.log('ss',this.file, this.fileList); + console.log(this.uniqueFile) + if(this.uniqueFile==null){ + this.msg.error("文件为空"); + return; + } + const formData = new FormData(); + if (this.uniqueFile != null) { + formData.append('file', this.uniqueFile); + this.templateInfo.category=this.getCategoryStr(this.templateInfo.categoryId) + formData.append('templateDto', JSON.stringify(this.templateInfo)); + const uploadTemplateRes$ = this.templateService + .upload(formData) + .pipe( + finalize(() => { + uploadTemplateRes$.unsubscribe(); + // this.tableLoading = false; + }) + ) + .subscribe( + message => { + console.log('message', message); + if (message.code === 0) { + // this.notifySvc.success(this.i18nSvc.fanyi('common.notify.edit-success'), ''); + this.msg.success(`模版文件上传成功`); + this.fileList=[] + } else { + this.msg.error(`模版上传失败:${message.msg}`); + // this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), message.msg); + } + // this.loadAlertConvergeTable(); + // this.tableLoading = false; + }, + error => { + console.log('err', error); + // this.tableLoading = false; + // this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), error.msg); + this.msg.error(`模版上传失败`, error.msg); + } + ); + } + } + + protected readonly window = window; +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/auth.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/auth.service.ts new file mode 100644 index 00000000000..0cbd1c4f472 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/auth.service.ts @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; + +import {Message} from '../pojo/Message'; + +const auth_login_uri = '/auth/login'; +const auth_refresh_uri = '/auth/refresh'; +const auth_register_uri = '/auth/register'; + +export interface LoginDTO { + type:number, + identifier:string, + credential:string, +} + +export interface SignUpDTO { + name:string, + email:string, + password:string, +} + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + constructor(private http: HttpClient) {} + + public tryLogin(data: LoginDTO): Observable> { + return this.http.post>(auth_login_uri,data); + } + + public register(data:SignUpDTO): Observable> { + return this.http.post>(auth_register_uri,data); + } + + public refreshToken(refreshToken: string): Observable> { + return this.http.post>(auth_refresh_uri, {"token":refreshToken}); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/category.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/category.service.ts new file mode 100644 index 00000000000..511fe94cb94 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/category.service.ts @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, HttpHeaders} from '@angular/common/http'; +import {Injectable, Optional} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +import {Message} from '../pojo/Message'; + +const category_uri = '/category/all'; + +@Injectable({ + providedIn: 'root' +}) +export class CategoryService { + constructor(@Optional() private http: HttpClient) {} + + private categorySubject = new BehaviorSubject([]); + + addCategoryList(arr: any[]) { + const currentData = this.categorySubject.getValue(); + this.categorySubject.next([...currentData, ...arr]); + } + + clearCategoryList() { + this.categorySubject.next([]); + } + + getCategoryList() { + return this.categorySubject.getValue(); + } + + public getAllCategoryByIsDel(isDel: number): Observable> { + if(this.http==null){ + console.log('http注册失败,为null') + } + return this.http.get>(category_uri+'/'+isDel, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/data.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/data.service.ts new file mode 100644 index 00000000000..3be9a3c4a3b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/data.service.ts @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +@Injectable() +export class DataService { + + private isLoginMessageSource = new BehaviorSubject(false); + isLoginMsg = this.isLoginMessageSource.asObservable(); + + constructor() { } + + sendLoginMsg(message: boolean) { + this.isLoginMessageSource.next(message) + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/local-storage.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/local-storage.service.ts new file mode 100644 index 00000000000..a9c34a72e0c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/local-storage.service.ts @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 } from '@angular/core'; + +const AuthorizationConst = 'Authorization'; +const RefreshTokenConst = 'refresh-token'; + +@Injectable({ + providedIn: 'root' +}) +export class LocalStorageService { + constructor() {} + + public putData(key: string, value: string) { + localStorage.setItem(key, value); + } + + public removeData(key: string) { + localStorage.removeItem(key); + } + + public getData(key: string): string | null { + const data = localStorage.getItem(key); + return data === null ? null : data; + } + + public getAuthorizationToken(): string | null { + return this.getData(AuthorizationConst); + } + + public getRefreshToken(): string | null { + return this.getData(RefreshTokenConst); + } + + public storageRefreshToken(token: string) { + return this.putData(RefreshTokenConst, token); + } + + public storageAuthorizationToken(token: string) { + return this.putData(AuthorizationConst, token); + } + + public hasAuthorizationToken() { + return localStorage.getItem(AuthorizationConst) != null; + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/star.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/star.service.ts new file mode 100644 index 00000000000..14ebb2b9c7b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/star.service.ts @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, HttpHeaders} from '@angular/common/http'; +import {Injectable, Optional} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +import {Message} from '../pojo/Message'; + +const template_star_uri = '/template/star'; +const star_page_user_uri='/star/page/user'; +const star_user_uri='/star'; +const star_isStar_uri='/star/isStar'; +const star_cancel_uri='/star/cancel'; + +@Injectable({ + providedIn: 'root' +}) +export class StarService { + constructor(@Optional() private http: HttpClient) {} + + public getTemplatePageByUserStar(userId: number, page:number, size:number): Observable> { + return this.http.get>(star_page_user_uri+'/'+userId+'?page='+page+'&size='+size); + } + + public getTemplateIdsByUser(userId: number): Observable> { + return this.http.get>(star_user_uri+'/'+userId); + } + + public assertTemplateStarByUser(userId: number,template:number): Observable> { + return this.http.get>(star_isStar_uri+'/'+userId+'/'+template); + } + + public cancelStarTemplate(userId: number, data:FormData): Observable> { + return this.http.post>(star_cancel_uri+'/'+userId,data); + } + + public starTemplate(data:FormData): Observable> { + return this.http.post>(template_star_uri,data); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/template.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/template.service.ts new file mode 100644 index 00000000000..c468260045f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/template.service.ts @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, HttpHeaders} from '@angular/common/http'; +import {Injectable, Optional} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +import {Message} from '../pojo/Message'; + +export interface TemplateVO { + id: number; + name: string; + description: string; + latest: number; + user: number; + categoryId: number; + tag:number; + download: number; + star:number, + create_time: string; + update_time: string; + off_shelf: number; + isDel: number; + starByNowUser:boolean; +} + +const template_count_uri = '/template/count'; +const template_upload_uri = '/template/upload'; +const template_page_uri = '/template/page'; +const template_page_name_uri='/template/page/name'; +const template_page_option_uri='/template/page/option'; +const template_page_order_uri='/template/page/order'; +const template_page_user_uri='/template/page/user'; +const template_download_uri = '/template/download/'; +const template_download_latest_uri = '/template/download/latest/'; +const template_page_category_uri = '/template/page/category'; + +@Injectable({ + providedIn: 'root' +}) +export class TemplateService { + constructor(@Optional() private http: HttpClient) {} + + private templateSubject = new BehaviorSubject([]); + private nowTemplateSubject=new BehaviorSubject(''); + + setNowTemplate(id:number){ + console.log(this.getTemplateById(id)); + this.nowTemplateSubject.next(this.getTemplateById(id)); + } + + getNowTemplate(){ + return this.nowTemplateSubject.value; + } + + setTemplateSubject(item: any[]) { + this.clearTemplateSubject(); + this.templateSubject.next([...item]); + } + + clearTemplateSubject(){ + this.templateSubject.next([]); + } + + getTemplateById(id:number) { + for (const item of this.templateSubject.getValue()) { + if (item.id === id) { + return item; + } + } + return null; + } + + public upload(data: FormData): Observable> { + return this.http.post>(template_upload_uri, data); + } + + public getTemplatePage(isDel: number, userId:number, page:number, size:number): Observable> { + return this.http.get>(template_page_uri+'/'+isDel+'/'+userId+'?page='+page+'&size='+size, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + + public getTemplatePageByUser(userId: number, page:number, size:number): Observable> { + return this.http.get>(template_page_user_uri+'/'+userId+'?page='+page+'&size='+size, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + + public getTemplatePageByOption(userId:number, allCategory:boolean,category: number[],nameLike:string,orderOption:number, + isDel: number, page:number, size:number): Observable> { + var categoryStr=''; + for (const id of category) { + categoryStr+=id+'_'; + } + categoryStr=categoryStr.substring(0,categoryStr.length-1); + if(page<0){ + page=0; + } + if(nameLike!=''){ + if(allCategory){ + return this.http.get>(template_page_name_uri+'/'+nameLike+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + else if(!allCategory){ + return this.http.get>(template_page_option_uri+'/'+nameLike+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + else{ + return this.http.get>(template_page_option_uri+'/'+nameLike+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'&category='+category, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + } + else{ + if(allCategory){ + return this.http.get>( + template_page_order_uri+'/'+orderOption+'/'+isDel+'/'+userId+'?page='+page+'&size='+size+'', + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + else if(!allCategory&&category.length>0){ + return this.http.get>( + template_page_category_uri+'/'+categoryStr+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'', + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + else{ + return this.http.get>( + template_page_category_uri+'/'+'_'+'/'+isDel+'/'+orderOption+'/'+userId+'?page='+page+'&size='+size+'', + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + } + } + + public getTemplateCount(isDel:number, offshelf:number): Observable { + return this.http.get>(`${template_count_uri}/${isDel}/${offshelf}`); + } + + public downloadTemplate(ownerId: number, templateId: number, version: string, versionId:number): Observable { + const httpOptions: Object = { + responseType: 'blob' + }; + return this.http.get(`${template_download_uri + ownerId}/${templateId}/${version}/${versionId}`, + httpOptions); + } + + public downloadLatestTemplate(user: number, templateId: number, latest: number): Observable { + const httpOptions: Object = { + responseType: 'blob' + }; + return this.http.get(`${template_download_latest_uri + user}/${templateId}/${latest}`, httpOptions); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/version.service.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/version.service.ts new file mode 100644 index 00000000000..4703bae6259 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/service/version.service.ts @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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, HttpHeaders} from '@angular/common/http'; +import {Injectable, Optional} from '@angular/core'; +import {Observable} from 'rxjs'; + +import {Message} from '../pojo/Message'; + +const template_upload_uri = '/template/upload'; +const version_page_uri = '/version/page'; +const version_get_uri = '/version/get'; +const share_uri='/share/getShareURL'; + +@Injectable({ + providedIn: 'root' +}) +export class VersionService { + constructor(@Optional() private http: HttpClient) {} + + public upload(data: FormData): Observable> { + return this.http.post>(template_upload_uri, data); + } + + public getVersion(id: number): Observable> { + return this.http.get>(version_get_uri+'/'+id); + } + + public getVersionPage(templateId :number, isDel: number, page:number, size:number): Observable> { + return this.http.get>(version_page_uri+'/'+templateId+'/'+isDel+'?page='+page+'&size='+size, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + + public shareVersion(versionId:number): Observable> { + return this.http.get>(share_uri+'/'+versionId, + {headers: new HttpHeaders({ 'Content-Type': 'application/json' }), responseType: 'json'}); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/app/shared/constants.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/app/shared/constants.ts new file mode 100644 index 00000000000..74fef9fe979 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/app/shared/constants.ts @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 CONSTANTS = { + VERSION: 'v1.6.0' +}; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/css/style.css b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/css/style.css new file mode 100644 index 00000000000..cdf072ffe55 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/css/style.css @@ -0,0 +1,2324 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Jost:wght@300;400;500;600;700;800;900&family=Montaga&family=Outfit:wght@300;400;500;600;700;800;900&family=Pacifico&family=Roboto:wght@300;400;500;700;900&family=Satisfy&family=Syne:wght@400;500;600;700;800&display=swap" rel="stylesheet'); +@font-face { + font-family: "sans-serif"; + font-weight: 500; + font-style: normal; + font-display: swap; +} +:root { + --tp-ff-heading: sans-serif; + + --tp-common-white: #ffffff; + --tp-common-black: #09052F; + --tp-common-black-2: #070707; + --tp-common-black-3: #000000; + --tp-common-black-4: #272F4D; + --tp-common-red: #FF3F4A; + --tp-common-green: #245757; + --tp-common-purple: #7D2EFF; + --tp-common-purple-2: #735CFC; + --tp-common-pink: #F94E41; + --tp-common-pink-2: #F8F3FF; + --tp-common-pink-3: #FAF6FC; + --tp-common-pink-4: #F43278; + --tp-heading-primary: #09052F; + --tp-grey-1: #EEEEF5; + --tp-grey-2: #F5F7FA; + --tp-grey-3: #5B646B; + --tp-grey-4: #787981; + --tp-text-body: #72747C; + --tp-theme-1: linear-gradient(90.07deg, #FF4E8D 32.43%, #AE34E8 58.79%, #3E8DFF 105.32%); + --tp-theme-2: #6B14FA; + --tp-theme-3: #951DF6; + --tp-border-1: #EFF1F5; +} + +@media (min-width: 1400px) { + .container, .container-lg, .container-md, .container-sm, .container-xl, .container-xxl { + max-width: 1250px; + } + .container-large { + max-width: 1490px; + } + .custom-container-1 { + max-width: 1270px; + } + .custom-container-3 { + max-width: 1330px; + } + .custom-container-4 { + max-width: 1420px; + } +} +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-size: 16px; + font-weight: 400; + line-height: 1.3; + overflow-x: hidden; + color: var(--tp-text-body); + font-family: sans-serif; +} + +html, body { + overflow-x: hidden; +} + +a { + text-decoration: none; + transition: 0.3s; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + font-weight: 800; + line-height: 1.1; + transition: 0.3s; + font-family: var(--tp-ff-heading), sans-serif; + color: var(--tp-heading-primary); +} + +img { + max-width: 100%; +} + +h1 { + font-size: 40px; +} + +h2 { + font-size: 32px; +} + +h3 { + font-size: 28px; +} + +h4 { + font-size: 24px; +} + +h5 { + font-size: 20px; +} + +h6 { + font-size: 16px; +} + +ul { + margin: 0; + padding: 0; +} + +p { + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: var(--tp-text-body); + font-family: sans-serif; +} + +.z-index { + position: relative; + z-index: 2; +} + +.z-index-5 { + position: relative; + z-index: 5; +} + +a, +.btn, +button, +input, +select, +textarea, +li, +img, +.transition-3, +h1, +h2, +h3, +h4, +h5, +h6 { + -webkit-transition: all 0.3s ease-out 0s; + -moz-transition: all 0.3s ease-out 0s; + -ms-transition: all 0.3s ease-out 0s; + -o-transition: all 0.3s ease-out 0s; + transition: all 0.3s ease-out 0s; +} + +li { + list-style: none; +} + +a:focus, +.button:focus { + text-decoration: none; + outline: none; +} + +a:focus, +a:hover { + color: inherit; + text-decoration: none; +} + +a, +button { + color: inherit; + outline: none; + border: none; + background: transparent; +} + +button:hover { + cursor: pointer; +} + +button:focus { + outline: 0; +} + +input, +textarea { + outline: none; + color: var(--tp-theme-2); +} +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: rgb(116, 116, 116); +} +input:-moz-placeholder, +textarea:-moz-placeholder { + color: rgb(116, 116, 116); +} +input::-moz-placeholder, +textarea::-moz-placeholder { + color: rgb(116, 116, 116); +} +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: rgb(116, 116, 116); +} + +input[type=color] { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + background: none; + border: 0; + cursor: pointer; + height: 100%; + width: 100%; + padding: 0; + border-radius: 50%; +} + +*::-moz-selection { + background: var(--tp-common-black); + color: var(--tp-common-white); + text-shadow: none; +} + +::-moz-selection { + background: var(--tp-common-black); + color: var(--tp-common-white); + text-shadow: none; +} + +::selection { + background: var(--tp-common-black); + color: var(--tp-common-white); + text-shadow: none; +} + +*::-moz-placeholder { + color: var(--tp-theme-1); + opacity: 1; +} + +*::placeholder { + color: var(--tp-theme-1); + opacity: 1; +} + +.fix { + overflow: hidden; +} + +.clear { + clear: both; +} + +.p-relative { + position: relative; +} + +input[type=text], input[type=email], input[type=tel], input[type=number], input[type=password], input[type=url], textarea { + outline: none; + background-color: #fff; + height: 64px; + width: 100%; + line-height: 56px; + font-size: 14px; + color: var(--tp-common-black); + padding-left: 25px; + padding-right: 25px; + border: 0; +} + +.tp-main-btn { + display: inline-block; + border-radius: 32px; + height: 64px; + line-height: 64px; + padding: 0 30px; + font-weight: 500; + font-size: 15px; + text-align: center; + text-transform: capitalize; + position: relative; + transition: 0.3s; + background: #FFF; + color: var(--tp-common-black); + box-shadow: 0px 1px 15px rgba(0, 0, 0, 0.06); +} +@media (max-width: 767px) { + .tp-main-btn { + padding: 0 25px; + } +} +.tp-main-btn i { + margin-left: 12px; +} +.tp-main-btn::before { + position: absolute; + content: ""; + background: linear-gradient(93.19deg, #FF4D8D 15.64%, #507EFB 84.55%); + border-radius: 32px; + width: 98%; + height: 98%; + left: 6px; + top: 6px; + transition: 0.3s; + z-index: -1; +} +.tp-main-btn:hover { + color: var(--tp-common-black); +} +.tp-main-btn:hover::before { + left: 1px; + top: 0; +} + +.btn-icon { + display:inline-flex; + align-items: center; + height: 61px; + padding: 0 50px; + /*display: inline-block;*/ + line-height: 61px; + font-weight: 500; + font-size: 16px; + text-align: center; + text-transform: uppercase; + transition: 0.3s; + background: var(--tp-common-purple-2); + color: var(--tp-common-white); +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .btn-icon { + display:inline-flex; + align-items: center; + height: 50px; + padding: 0 25px; + line-height: 50px; + font-size: 14px; + } +} +@media (max-width: 767px) { + .btn-icon { + display:inline-flex; + align-items: center; + height: 50px; + padding: 0 25px; + line-height: 50px; + font-size: 12px; + } +} +.btn-icon:hover { + background-color: #FF8717; + color: var(--tp-common-white); +} + +.btn-no-icon { + height: 61px; + padding: 0 50px; + display: inline-block; + line-height: 61px; + font-weight: 500; + font-size: 16px; + text-align: center; + text-transform: uppercase; + transition: 0.3s; + background: var(--tp-common-purple-2); + color: var(--tp-common-white); +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .btn-no-icon { + height: 50px; + padding: 0 25px; + line-height: 50px; + font-size: 14px; + } +} +@media (max-width: 767px) { + .btn-no-icon { + height: 50px; + padding: 0 25px; + line-height: 50px; + font-size: 12px; + } +} +.btn-no-icon:hover { + background-color: #FF8717; + color: var(--tp-common-white); +} + +@keyframes section-animation { + 0% { + width: 0; + } + 15% { + width: 100%; + } + 85% { + opacity: 1; + } + 90% { + width: 100%; + opacity: 0; + } + to { + width: 0; + opacity: 0; + } +} + +@keyframes scroll { + 0% { + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } + 100% { + -webkit-transform: translateY(8px); + -moz-transform: translateY(8px); + -ms-transform: translateY(8px); + -o-transform: translateY(8px); + transform: translateY(8px); + } +} + +.dark #preloader { + background-color: var(--tp-theme-1); +} + +#preloader { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f7f7f7; + z-index: 999999; +} + +.preloader { + width: 50px; + height: 50px; + display: inline-block; + padding: 0px; + text-align: left; + box-sizing: border-box; + position: absolute; + top: 50%; + left: 50%; + margin-left: -25px; + margin-top: -25px; +} + +.preloader span { + position: absolute; + display: inline-block; + width: 50px; + height: 50px; + border-radius: 100%; + background: var(--tp-theme-1); + -webkit-animation: preloader 1.3s linear infinite; + animation: preloader 1.3s linear infinite; +} + +.preloader span:last-child { + animation-delay: -0.9s; + -webkit-animation-delay: -0.9s; +} + +@keyframes preloader { + 0% { + transform: scale(0, 0); + opacity: 0.5; + } + 100% { + transform: scale(1, 1); + opacity: 0; + } +} +@-webkit-keyframes preloader { + 0% { + -webkit-transform: scale(0, 0); + opacity: 0.5; + } + 100% { + -webkit-transform: scale(1, 1); + opacity: 0; + } +} + +.grey-bg { + background: var(--tp-grey-1); +} + +.theme-bg { + background: var(--tp-theme-1); +} + +.tp-breadcrumb-height { + padding-top: 65px; + padding-bottom: 110px; + background-repeat: no-repeat; + background-size: cover; + object-fit: cover; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-breadcrumb-height { + padding: 120px 0; + } +} + +.tp-breadcrumb__title { + font-size: 55px; + font-style: normal; + font-weight: 500; + text-transform: capitalize; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px), only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-breadcrumb__title { + font-size: 50px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-breadcrumb__title { + font-size: 50px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-breadcrumb__title { + font-size: 45px; + } +} +@media (max-width: 767px) { + .tp-breadcrumb__title { + font-size: 40px; + } +} +.tp-breadcrumb__list { + display: inline-block; + padding: 5px 20px; + margin-bottom: 15px; + background-color: var(--tp-common-white); + border-radius: 30px; +} +.tp-breadcrumb__list span { + color: var(--tp-common-pink-4); + font-size: 14px; + font-style: normal; + font-weight: 700; + text-transform: uppercase; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-breadcrumb__list span { + font-size: 13px; + } +} +.tp-breadcrumb__list span.dvdr i { + color: var(--tp-common-white); + font-weight: 400; + font-size: 13px; +} + +.tp-custom-accordion .accordion-buttons { + position: relative; + width: 100%; + padding: 22px 25px; + background-color: var(--tp-common-white); + text-align: left; + font-weight: 700; + font-size: 18px; + margin-bottom: 25px; + border: 1px solid transparent; + transition: 0.3s; + border-radius: 4px; + color: var(--tp-theme-1); + line-height: 1.2; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-custom-accordion .accordion-buttons { + font-size: 17px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-custom-accordion .accordion-buttons { + padding: 25px 28px; + font-size: 18px; + } +} +@media (max-width: 767px) { + .tp-custom-accordion .accordion-buttons { + font-size: 16px; + padding: 25px 40px 25px 28px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-custom-accordion .accordion-buttons { + font-size: 17px; + } +} +.tp-custom-accordion .accordion-buttons::after { + position: absolute; + content: "\f068"; + font-family: sans-serif; + top: 50%; + transform: translateY(-50%); + right: 30px; + font-size: 16px; + opacity: 1; + /*color: var(--tp-common-orange);*/ +} +@media (max-width: 767px) { + .tp-custom-accordion .accordion-buttons::after { + top: 35px; + right: 25px; + font-size: 13px; + } +} +.tp-custom-accordion .accordion-buttons:not(.collapsed) { + background: rgba(255, 255, 255, 0.5); + box-shadow: 0 11px 12px 0 rgba(0, 0, 0, 0.08); +} +.tp-custom-accordion .accordion-buttons.collapsed { + border: 1px solid #E3EBF4; +} +.tp-custom-accordion .accordion-buttons.collapsed::after { + content: "\f067"; +} +.tp-custom-accordion .collapsed { + position: relative; + z-index: 99; +} +.tp-custom-accordion .accordion-body { + background-color: var(--tp-common-white); + padding-bottom: 20px; + padding-left: 25px; + padding-right: 50px; + position: relative; + font-size: 16px; + font-weight: 400; + line-height: 28px; + z-index: 1; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-custom-accordion .accordion-body { + font-size: 14px; + padding-right: 65px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .tp-custom-accordion .accordion-body { + font-size: 14px; + } +} +@media (max-width: 767px) { + .tp-custom-accordion .accordion-body { + font-size: 13px; + padding-right: 0; + } +} +.tp-custom-accordion .accordion-body::after { + position: absolute; + content: ""; + top: 6px; + left: 70px; + width: 1px; + height: 75px; + /*background-color: var(--tp-common-orange);*/ +} +@media (max-width: 767px) { + .tp-custom-accordion .accordion-body::after { + display: none; + visibility: hidden; + } +} + +.tp-service-details-faq .accordion-items { + border: 1px solid rgba(4, 18, 31, 0.08); + border-radius: 0; +} +.tp-service-details-faq .accordion-body { + border-top: 1px solid rgba(4, 18, 31, 0.08); +} + +.tp-title-shape { + position: absolute; + bottom: -20px; + left: 0; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-title-shape { + bottom: -15px; + } +} +@media (max-width: 767px) { + .tp-title-shape { + bottom: -13px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-title-shape { + bottom: -20px; + } +} +.tp-title-shape svg { + animation: section-animation 4s infinite; +} + +.tp-hero-subtitle { + font-weight: 500; + font-size: 20px; + line-height: 27px; + color: var(--tp-common-black); + position: relative; + display: inline-block; + margin-bottom: 23px; +} +.tp-hero-subtitle::before { + content: ""; + width: 9px; + height: 2px; + background-color: var(--tp-common-red); + display: inline-block; + margin-right: 8px; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px) { + .tp-hero-subtitle { + font-size: 16px; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-hero-subtitle { + font-size: 17px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .tp-hero-subtitle { + font-size: 15px; + } +} +@media (max-width: 767px) { + .tp-hero-subtitle { + font-size: 15px; + padding: 8px 20px; + } +} + +.tp-hero-title { + font-weight: 500; + line-height: 1.1; + font-size: 70px; + text-transform: capitalize; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px) { + .tp-hero-title { + font-size: 65px; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-hero-title { + font-size: 65px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-hero-title { + font-size: 58px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-hero-title { + font-size: 50px; + } + .tp-hero-title br { + display: none; + } +} +@media (max-width: 767px) { + .tp-hero-title { + font-size: 42px; + } + .tp-hero-title br { + display: none; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-hero-title { + font-size: 48px; + } + .tp-hero-title br { + display: none; + } +} +@media only screen and (min-width: 440px) and (max-width: 575px) { + .tp-hero-title { + font-size: 54px; + } +} +.tp-hero-title span { + background: linear-gradient(90.07deg, #FF4E8D 32.43%, #AE34E8 58.79%, #3E8DFF 105.32%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.tp-slider-title-shape { + position: absolute; + bottom: -33px; + left: 0; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px) { + .tp-slider-title-shape { + bottom: -27px; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-slider-title-shape { + bottom: -27px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-slider-title-shape { + bottom: -25px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-slider-title-shape { + bottom: -24px; + } +} +@media (max-width: 767px) { + .tp-slider-title-shape { + bottom: -20px; + } +} +.tp-slider-title-shape svg { + animation: section-animation 4s infinite; +} + +.header-sticky { + position: fixed; + top: 0; + left: 0; + right: 0; + opacity: 1; + visibility: visible; + width: 100%; + z-index: 999; + background-color: var(--tp-common-white); + box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; + animation: 0.5s ease-in-out 0s normal none 1 running fadeInDown; +} + +.tp-header-top__space { + padding: 9px 0; +} + +.tp-header-top__left-box span { + color: var(--tp-common-white); + font-weight: 500; + font-size: 16px; + text-transform: capitalize; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), (max-width: 767px) { + .tp-header-top__left-box span { + font-size: 14px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-header-top__left-box span { + font-size: 13px; + } +} +.tp-header-top__left-box svg { + margin-right: 10px; +} +.tp-header-top__shop-box { + margin-left: 20px; +} +.tp-header-top__shop-box span { + font-weight: 500; + font-size: 16px; + color: var(--tp-common-white); + margin-right: 12px; + text-transform: capitalize; +} +.tp-header-top__shop-box > a { + font-weight: 500; + font-size: 13px; + color: var(--tp-common-white); + width: 85px; + display: inline-block; + height: 25px; + line-height: 24px; + text-align: center; + background: rgba(255, 255, 255, 0.2); + border-radius: 2px; +} + +.tp-header__main-menu { + margin-left: -35px; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px) { + .tp-header__main-menu { + margin-left: -75px; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__main-menu { + margin-left: 0px; + } +} +.tp-header__main-menu ul li { + list-style-type: none; + display: inline-block; + position: relative; + border-right: 1px solid #fff; + padding: 0 38px; +} +.tp-header__main-menu ul li:hover .submenu { + opacity: 1; + visibility: visible; + -webkit-transform: scaleY(1); + -moz-transform: scaleY(1); + -ms-transform: scaleY(1); + -o-transform: scaleY(1); + transform: scaleY(1); +} +.tp-header__main-menu ul li:hover > a { + color: var(--tp-common-pink-4); +} +.tp-header__main-menu ul li .submenu { + position: absolute; + top: 100%; + left: -5px; + width: 240px; + z-index: 999; + padding: 30px 40px; + opacity: 0; + visibility: hidden; + transition: 0.4s; + transform: scaleY(0); + transform-origin: top center; + text-align: start; + background-color: var(--tp-common-white); + border-top: 5px solid var(--tp-common-pink-4); + box-shadow: rgba(149, 157, 165, 0.2) 0 8px 24px; +} +.tp-header__main-menu ul li .submenu > li { + padding: 0; + margin: 0 0 15px; + display: block; +} +.tp-header__main-menu ul li .submenu > li:last-child { + margin-bottom: 0; +} +.tp-header__main-menu ul li .submenu > li a { + padding: 0; + font-size: 14px; + text-transform: uppercase; + color: var(--tp-common-black); + position: relative; +} +.tp-header__main-menu ul li .submenu > li a::after { + content: ""; + position: absolute; + bottom: 0; + right: 0; + left: auto; + height: 1px; + width: 0; + background-color: var(--tp-common-pink); + transition: 0.7s; + display: inline-block; +} +.tp-header__main-menu ul li .submenu > li:hover > a { + color: var(--tp-common-pink-4); +} +.tp-header__main-menu ul li .submenu > li:hover > a::after { + width: 100%; + right: auto; + left: 0; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__main-menu ul li { + padding: 0 28px; + } +} +.tp-header__main-menu ul li:last-child { + border-right: none; +} +.tp-header__main-menu ul li > a { + font-weight: 500; + font-size: 16px; + line-height: 22px; + color: var(--tp-common-black); + padding: 34px 0px; + display: inline-block; + text-transform: capitalize; + transition: 0.3s; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__main-menu ul li > a { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-header__main-menu ul li > a { + font-size: 14px; + } +} + +.tp-header__chat-box { + margin-left: 43px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__chat-box { + display: none; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__chat-box { + display: none; + } +} +@media (max-width: 767px) { + .tp-header__chat-box { + display: none; + } +} +.tp-header__chat-box span { + width: 50px; + height: 50px; + line-height: 50px; + display: inline-block; + background: #735CFC; + border-radius: 50%; + text-align: center; + margin-left: 10px; +} +.tp-header__chat-box a { + font-weight: 500; + font-size: 16px; + letter-spacing: 0.05em; + text-transform: capitalize; + color: var(--tp-common-black); +} +.tp-header__icon-box span { + padding: 0 7px; + display: inline-block; +} +.tp-header__icon-box span.heart { + color: var(--tp-common-black); + font-size: 20px; + font-weight: 300; + display: inline-block; + transform: translateY(4px); +} +.tp-header__right-box { + margin-left: -120px; +} +.tp-header__right-box ul li { + display: inline-block; +} +.tp-header__icon-text { + position: absolute; + top: -11px; + right: -3px; + /*display: inline-block;*/ + font-family: "Jost", sans-serif; + font-weight: 500; + font-size: 12px; + color: var(--tp-common-white); + width: 16px; + height: 16px; + line-height: 16px; + border-radius: 50%; + background: #DD1D29; + display: flex; + align-items: center; + justify-content: center; + font-style: normal; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-header__left-box { + padding: 10px 0; + } +} +.tp-header__logo { + width: 110px; + height: auto; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-header__logo { + margin: 10px 0; + } +} + +.tp-header-2__bar { + margin-left: 25px; +} +.tp-header-2__bar.bar-height { + margin: 10px 0; +} +.tp-header-2__bar button i { + font-size: 23px; + color: var(--tp-common-white); + display: inline-block; + width: 50px; + height: 50px; + line-height: 50px; + text-align: center; + border-radius: 50%; + background: var(--tp-common-purple); + box-shadow: 0px 4px 8px rgba(51, 92, 154, 0.04); +} + +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__main-menu ul li .submenu { + position: absolute; + left: -200px; + } +} + +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-header__main-menu ul li .submenu { + position: absolute; + left: -100px; + } +} + +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .submenu { + position: absolute; + left: -200px; + } +} + +.tp-hero__bg { + padding-top: 235px; + padding-bottom: 205px; + position: relative; + z-index: -2; + background-repeat: no-repeat; + background-size: cover; +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-hero__bg { + padding-top: 180px; + padding-bottom: 160px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-hero__bg { + padding-top: 140px; + padding-bottom: 130px; + } +} +@media (max-width: 767px) { + .tp-hero__bg { + padding-top: 120px; + padding-bottom: 100px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-hero__bg { + padding-top: 150px; + } +} +.tp-hero__left-text p { + font-size: 20px; + line-height: 32px; + padding-right: 50px; + margin-bottom: 40px; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px) { + .tp-hero__left-text p { + font-size: 16px; + padding-right: 160px; + } +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-hero__left-text p { + font-size: 16px; + padding-right: 160px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-hero__left-text p { + font-size: 15px; + padding-right: 75px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-hero__left-text p { + font-size: 18px; + padding-right: 0; + } +} +@media (max-width: 767px) { + .tp-hero__left-text p { + font-size: 15px; + padding-right: 0; + } +} +.tp-hero__section-box { + padding-bottom: 30px; +} +.tp-hero__thumb-box { + padding-right: 45px; + position: relative; + z-index: 12; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-hero__thumb-box { + padding-right: 0; + } +} + +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-hero__left-box { + margin-bottom: 90px; + } +} + +.tp-feature__border { + padding-top: 65px; + padding-bottom: 20px; + border-bottom: 1px solid var(--tp-border-1); +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-feature__border { + border: none; + } +} +.tp-feature__content p { + margin-bottom: 0; + font-weight: 400; + font-size: 16px; + line-height: 24px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-feature__content p { + font-size: 14px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-feature__content p { + font-size: 14px; + padding-right: 70px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-feature__content p { + font-size: 14px; + } +} +.tp-feature__title { + font-weight: 500; + font-size: 24px; + padding-bottom: 3px; + text-transform: capitalize; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-feature__title { + font-size: 22px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-feature__title { + font-size: 21px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-feature__title { + font-size: 21px; + } +} +.tp-feature__icon { + margin-right: 25px; +} +.tp-feature__item { + position: relative; +} +.tp-feature__item::after { + content: ""; + border: 1px dashed #CACACA; + height: 55px; + width: 1px; + top: 50%; + transform: translateY(-50%); + right: -30px; + position: absolute; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-feature__item::after { + display: none; + } +} +.tp-feature__item.border-none::after { + display: none; +} + +.feature-col-2 { + margin-left: 35px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .feature-col-2 { + margin-left: 0; + } +} + +.feature-col-3 { + margin-left: 28px; +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .feature-col-3 { + margin-left: 0; + } +} + +.table td, .table th { + border-top: 1px solid #eaedff; +} + +.tp-service-widget { + position: sticky; + top: 150px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), only screen and (min-width: 576px) and (max-width: 767px), (max-width: 767px) { + .tp-service-widget { + position: inherit; + } +} +.tp-service-widget-tab { + margin-right: 40px; +} +@media only screen and (min-width: 1400px) and (max-width: 1599px), only screen and (min-width: 1200px) and (max-width: 1399px), only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-service-widget-tab { + margin-right: 0; + } +} +.tp-service-widget-tab ul li { + list-style: none; + margin-bottom: 13px; +} +.tp-service-widget-tab ul li .active { + background-color: var(--tp-common-purple-2); + color: var(--tp-common-white); +} +.tp-service-widget-tab ul li .active i { + background-color: var(--tp-common-purple-2); +} +.tp-service-widget-tab ul li a { + position: relative; + font-weight: 600; + font-size: 18px; + line-height: 21px; + color: #101C2A; + background: #F8F8F8; + display: inline-block; + width: 100%; + padding: 24px 20px; + transition: 0.3s; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px), only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-service-widget-tab ul li a { + font-size: 17px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-service-widget-tab ul li a { + font-size: 17px; + } +} +.tp-service-widget-tab ul li a:hover { + background-color: var(--tp-common-purple-2); + color: var(--tp-common-white); +} +.tp-service-widget-tab ul li a i { + position: absolute; + top: 38%; + right: 20px; + transition: 0.3s; +} + +.tp-service-contact-form { + padding: 40px 30px 10px 30px; + /*padding-bottom: 65px;*/ + background-repeat: no-repeat; + background-size: cover; +} +.tp-service-contact-form h6 { + color: var(--tp-common-black-3); + font-size: 28px; + font-weight: 500; + line-height: 30px; + letter-spacing: -1.12px; + margin-bottom: 17px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-service-contact-form h6 { + font-size: 26px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-service-contact-form h6 { + font-size: 21px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-service-contact-form h6 { + font-size: 24px; + } +} +@media (max-width: 767px) { + .tp-service-contact-form h6 { + font-size: 20px; + } +} +.tp-service-contact-form span { + color: #707481; + font-size: 16px; + font-weight: 400; + line-height: 26px; + display: block; + margin-bottom: 45px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px), only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-service-contact-form span { + font-size: 14px; + } +} + +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons { + padding: 38px 28px; +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons:hover { + color: var(--tp-theme-1); +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons::after { + top: 38px; +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons:not(.collapsed) { + background-color: transparent; + color: var(--tp-common-black); +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons:not(.collapsed):hover { + color: var(--tp-theme-1); +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-body { + border-top: 1px solid rgba(0, 82, 204, 0.1); + margin: 0px 20px; + padding-left: 0; + padding-right: 0; +} +.tp-faq-inner__customize .tp-custom-accordion .accordion-buttons:not(.collapsed)::after { + color: var(--tp-common-black); +} + +.tp-contact-4__comment-agree .form-check-label { + font-size: 16px; + font-family: "DM Sans", sans-serif; + font-style: normal; + font-weight: 400; + line-height: 26px; + color: #838383; + cursor: pointer; +} +@media (max-width: 767px) { + .tp-contact-4__comment-agree .form-check-label { + padding-top: 10px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-contact-4__comment-agree .form-check-label { + font-size: 14px; + } +} +@media (max-width: 767px) { + .tp-contact-4__comment-agree .form-check-label { + font-size: 14px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-contact-4__comment-agree .form-check-label { + padding-top: 0px; + font-size: 12px; + } +} +.tp-contact-4__comment-agree .form-check-label span { + color: var(--tp-theme-2); +} +.tp-contact-4__comment-agree .form-check-label span.red { + color: #F32020; +} +.tp-contact-4__comment-agree input { + height: 17px; + width: 16px; + margin-right: 12px; + color: #949392; +} +.tp-contact-4__comment-agree .form-check-input:checked { + background-color: var(--tp-theme-2); + border-color: transparent; +} +.tp-contact-4__comment-agree .form-check-input:focus { + box-shadow: none; +} +.tp-contact-4__comment-agree .form-check-input.form-check-input[type=checkbox] { + border-radius: 2px; +} +@media (max-width: 767px) { + .tp-contact-4__comment-agree.label-2 .form-check-label { + font-size: 12px; + padding-top: 0px; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-contact-4__comment-agree.label-2 .form-check-label { + font-size: 14px; + } +} + +.tp-register__form-box { + padding: 70px 58px 70px 40px; + border: 1px solid #E0E0E0; + margin: 0 41px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px), only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .tp-register__form-box { + padding: 70px 60px; + margin: 0; + } +} +@media (max-width: 767px) { + .tp-register__form-box { + padding: 70px 10px; + margin: 0; + } +} +@media only screen and (min-width: 576px) and (max-width: 767px) { + .tp-register__form-box { + padding: 70px 30px; + margin: 0; + } +} +.tp-register__form-title h6 { + color: var(--tp-common-black-3); + font-size: 23px; + font-weight: 500; + line-height: 28px; + text-transform: capitalize; + margin-bottom: 25px; +} +.tp-register__form-title span { + color: #696866; + font-size: 16px; + font-weight: 400; + line-height: 26px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-register__form-title span { + font-size: 14px; + } + .tp-register__form-title span br { + display: none; + } +} +.tp-register__input-box { + position: relative; +} +.tp-register__input-box label { + color: var(--tp-common-black-3); + font-family: var(--tp-ff-heading), sans-serif; + font-size: 16px; + font-weight: 500; + line-height: 26px; + padding-bottom: 10px; +} +.tp-register__input-box input { + height: 60px; + line-height: 60px; + border: 1px solid #E0E0E0; + margin-bottom: 30px; +} +.tp-register__input-box input:focus { + border: 1px solid var(--tp-common-purple-2); +} + +.tp-register__input-text { + color: #F32020; + font-size: 14px; + font-weight: 500; + line-height: 26px; + position: absolute; + top: 0; + right: 0; +} +.tp-register__input-text:hover { + color: #F32020; +} + +.tp-fea-product__thumb { + text-align: center; + overflow: hidden; + border-radius: 15px; +} +.tp-fea-product__thumb img { + border-radius: 15px; + width: 100%; + transition: 0.5s; +} +.tp-fea-product__thumb-text { + border-radius: 40px; + background: #FF111F; + position: absolute; + top: 10px; + left: 10px; + display: inline-block; +} +.tp-fea-product__thumb-text span { + color: var(--tp-common-white); + font-size: 12px; + font-weight: 500; + text-transform: uppercase; + padding: 3px 15px; + display: inline-block; +} +.tp-fea-product__content { + padding: 0 15px 0; +} +.tp-fea-product__item { + padding: 13px 11px 18px; + transition: 0.3s; + border-radius: 15px; + position: relative; + z-index: 1; +} +.tp-fea-product__item:hover { + background-color: var(--tp-common-white); +} +.tp-fea-product__item:hover .template_card__icon-box { + opacity: 1; + visibility: visible; + top: 50%; + transform: translateY(-50%); +} +.tp-fea-product__item:hover .tp-fea-product__link-box { + opacity: 1; + visibility: visible; + margin-top: -17px; +} +.tp-fea-product__item:hover .tp-fea-product__price { + opacity: 0; + visibility: hidden; +} +.tp-fea-product__item:hover .tp-fea-product__thumb img { + transform: scale(1.2) rotate(-1deg); +} +.template_card__icon-box { + position: absolute; + top: 20%; + left: 36%; + /*right: 0;*/ + transition: 0.5s; + opacity: 0; + visibility: hidden; +} +.template_card__icon-box a { + border-radius: 5px; + border: 0 solid #D72323; + background: var(--tp-common-white); + width: 40px; + height: 40px; + line-height: 36px; + text-align: center; + display: inline-block; + transition: 0.3s; + margin: 0 2px; +} +.template_card__icon-box a svg { + transition: 0.3s; + color: var(--tp-common-black); + width: 20px; +} +.template_card__icon-box a:hover { + background-color: var(--tp-common-purple-2); +} +.template_card__icon-box a:hover svg { + color: var(--tp-common-white); +} + +.tp-fea-product__price { + transition: 0.3s; +} +.tp-fea-product__price span { + font-weight: 500; + font-size: 15px; + color: #ED1D24; + font-family: var(--tp-ff-heading), sans-serif; + margin-right: 8px; +} +.tp-fea-product__price del { + font-size: 15px; + color: #9695A0; + font-family: var(--tp-ff-heading), sans-serif; +} +.tp-fea-product__star { + margin-bottom: 18px; +} +.tp-fea-product__star i { + color: #FAB311; + padding-right: 2px; +} +.tp-fea-product__star i.color { + color: #D2D3DA; +} +.tp-fea-product__title-sm { + font-weight: 500; + font-size: 16px; + line-height: 23px; + text-transform: capitalize; + margin-bottom: 10px; + transition: 0.3s; +} +.tp-fea-product__title-sm:hover { + color: var(--tp-theme-2); +} + +.tp-fea-product__item-2:hover .tp-fea-product__price { + opacity: 1; + visibility: visible; +} + +.tp-product__filter{ + position: relative; +} +.tp-product__filter .nice-select { + position: relative; + background: var(--tp-common-white); + border-radius: 0; + padding: 0 80px 0 30px; + width: 100%; + height: 60px; + line-height: 60px; + border: 1px solid #e6e9e9; + font-size: 14px; + color: var(--tp-common-black); +} +.tp-product__filter .nice-select.open::after { + transform: translateY(-45%) rotate(-180deg); +} +.tp-product__filter .nice-select .option.selected { + font-weight: 400; + color: var(--tp-common-black); +} +.tp-product__filter .nice-select::after { + border: none; + background-color: transparent; + transform: translateY(-50%); + margin-top: 0; + right: 30px; + content: "\f107"; + transform-origin: center; + color: #77829D; + height: auto; + width: auto; + font-size: 20px; + font-weight: 400; +} +.tp-product__filter .nice-select ul { + padding: 25px; + width: 100%; + box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; + border-radius: 0; +} +.tp-product__filter .nice-select ul li { + color: #77829D; + margin-bottom: 15px; + font-weight: 400; + font-size: 16px; + padding: 0; +} +.tp-product__filter .nice-select ul li:last-child { + margin-bottom: 0; +} +.tp-product__filter .nice-select .option { + line-height: 1; + min-height: 0; +} +.tp-product__filter .nice-select.open ul { + opacity: 1; + visibility: visible; +} +.tp-product__input { + position: relative; +} +.tp-product__input input { + padding: 0 80px 0 30px; + width: 100%; + height: 40px; + line-height: 40px; + transition: 0.3s; + border: 1px solid #d9d9d9; +} +.tp-product__input input:focus { + border: 1px solid var(--tp-common-purple-2); +} + +.tp-shop-details__wrapper { + /*margin-bottom: 120px;*/ +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-shop-details__wrapper { + /*margin-bottom: 60px;*/ + } +} + +@media (max-width: 767px) { + .tp-shop-details__quantity-wrap { + flex-wrap: wrap; + } +} +.tp-shop-details__quantity { + background-color: #F7F7F7; + width: 205px; + height: 67px; + position: relative; + margin-right: 15px; +} +@media (max-width: 767px) { + .tp-shop-details__quantity { + margin-bottom: 20px; + } +} +.tp-shop-details__quantity input { + border: 0; + background-color: transparent; + width: 100%; + height: 100%; + text-align: center; + color: var(--tp-common-black); +} +.tp-shop-details__quantity .tp-cart-minus { + position: absolute; + top: 0; + left: 0; + height: 64px; + width: 64px; + line-height: 64px; + text-align: center; + color: var(--tp-common-black); +} +.tp-shop-details__quantity .tp-cart-plus { + position: absolute; + top: 0; + right: 0; + height: 64px; + width: 64px; + line-height: 64px; + text-align: center; + color: var(--tp-common-black); +} +.tp-shop-details__btn { + line-height: 0; +} +@media (max-width: 767px) { + .tp-shop-details__btn { + margin-bottom: 10px; + } +} + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-shop-details__right-warp { + margin-bottom: 50px; + } +} +.tp-shop-details__title-sm { + font-weight: 700; + font-size: 28px; + color: #060728; + padding-bottom: 15px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-shop-details__title-sm { + font-size: 32px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-shop-details__title-sm { + font-size: 29px; + } +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .tp-shop-details__title-sm { + font-size: 29px; + } + .tp-shop-details__title-sm br { + display: none; + } +} +@media (max-width: 767px) { + .tp-shop-details__title-sm { + font-size: 30px; + } + .tp-shop-details__title-sm br { + display: none; + } +} + +.tp-shop-details__product-info { + margin-bottom: 30px; +} +.tp-shop-details__product-info ul li { + color: rgba(20, 33, 43, 0.8); + font-size: 15px; + font-weight: 400; + margin-bottom: 23px; + list-style-type: none; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-shop-details__product-info ul li { + font-size: 17px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px) { + .tp-shop-details__product-info ul li { + font-size: 15px; + } +} +@media (max-width: 767px) { + .tp-shop-details__product-info ul li { + font-size: 16px; + } +} +.tp-shop-details__product-info ul li:last-child { + margin-bottom: 0; +} +.tp-shop-details__product-info ul li > span { + color: #232323; + font-family: var(--tp-ff-heading), serif; + font-size: 16px; + font-weight: 600; +} + +.pro-details-nav { + background: #F9FAFB; + display: inline-block; + padding: 7px 7px; +} + +.pro-details-nav-btn { + border: none; +} +.pro-details-nav-btn li { + font-weight: 500; + font-size: 18px; + color: var(--tp-text-body); + position: relative; +} +.pro-details-nav-btn li button span { + position: relative; + z-index: 9; +} +.pro-details-nav-btn li button::before { + content: ""; + height: 100%; + width: 102%; + top: 0; + left: -1px; + background: #fff; + position: absolute; + z-index: 3; + opacity: 0; + visibility: hidden; +} +.pro-details-nav-btn li button.active::before { + opacity: 1; + visibility: visible; +} +.pro-details-nav-btn li::after { + position: absolute; + content: ""; + height: 40px; + width: 1px; + background: #DFE3E9; + top: 50%; + transform: translateY(-50%); +} +@media (max-width: 767px) { + .pro-details-nav-btn li::after { + display: none; + } +} +.pro-details-nav-btn li:last-child::after { + display: none; +} +@media (max-width: 767px) { + .pro-details-nav-btn li { + font-size: 16px; + } +} +.pro-details-nav-btn li .nav-links { + padding: 20px 45px; + border-radius: 5px; +} +@media only screen and (min-width: 768px) and (max-width: 991px) { + .pro-details-nav-btn li .nav-links { + padding: 10px 20px; + } +} +@media (max-width: 767px) { + .pro-details-nav-btn li .nav-links { + padding: 5px 15px; + } +} +.pro-details-nav-btn li .nav-links.active { + background: var(--tp-common-white); + color: var(--tp-common-black); +} + +.table .add-info { + font-size: 18px; + font-weight: 500; +} + +.table td { + padding: 18px; +} + +.product-details-list-box > span { + color: var(--tp-common-black-3); + font-size: 22px; + font-weight: 700; + display: block; + margin-bottom: 30px; +} +.product-details-list-box ul { + display: inline-block; +} +.product-details-list-box ul li { + color: #445658; + font-size: 16px; + font-weight: 400; + width: 50%; + float: left; + padding-left: 30px; + position: relative; + padding-bottom: 22px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .product-details-list-box ul li { + width: 100%; + } +} +.product-details-list-box ul li svg { + color: var(--tp-common-purple-2); + position: absolute; + top: 3px; + left: 0; +} + +.tp-shop-widget-title { + color: var(--tp-common-black-3); + font-family: var(--tp-ff-heading), sans-serif; + font-size: 18px; + font-weight: 500; + text-transform: capitalize; + padding-bottom: 5px; + margin-bottom: 20px; +} + +.tp-shop-widget-tag span { + color: #77787B; + font-size: 14px; + font-weight: 500; + text-transform: capitalize; + display: inline-block; + padding: 0 15px; + height: 36px; + line-height: 36px; + background-color: #F6F6F6; + border-radius: 30px; + margin-bottom: 15px; + margin-right: 3px; + transition: 0.3s; +} +.tp-shop-widget-tag span:hover { + background-color: var(--tp-common-purple-2); + color: var(--tp-common-white); +} +.tp-shop-widget-categories { + height: 300px; + overflow-y: scroll; + overscroll-behavior-y: contain; + scrollbar-width: none; + padding-right: 10px; +} + +.tp-shop-widget-categories ul li { + list-style: none; + width: 100%; +} +.tp-shop-widget-categories ul li:not(:last-child) { + margin-bottom: 30px; +} +.tp-shop-widget-categories ul li a { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; +} +.tp-shop-widget-categories ul li a:hover { + color: var(--tp-common-purple-2); +} +.tp-shop-widget-categories ul li a:hover::after { + background-color: var(--tp-common-purple-2); +} + +.tp-footer__logo { + padding-bottom: 22px; + width: 110px; + height: auto; +} +.tp-footer__icon { + margin-right: 15px; +} +.tp-footer__text p { + font-weight: 500; + font-size: 18px; + line-height: 30px; + margin-bottom: 35px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-footer__text p { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-footer__text p { + font-size: 14px; + } +} +.tp-footer__text a { + font-weight: 500; + font-size: 18px; + color: var(--tp-common-black); +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-footer__text a { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-footer__text a { + font-size: 14px; + } +} +.tp-footer__widget-title { + font-weight: 500; + font-size: 22px; + margin-bottom: 25px; + padding-top: 5px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-footer__widget-title { + font-size: 20px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-footer__widget-title { + font-size: 18px; + } +} +.tp-footer__list ul li { + font-weight: 500; + font-size: 18px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-footer__list ul li { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-footer__list ul li { + font-size: 14px; + } +} +.tp-footer__list ul li:not(:last-child) { + padding-bottom: 16px; +} +.tp-footer__list ul li a { + position: relative; +} +.tp-footer__list ul li a:hover::after { + opacity: 1; + visibility: visible; + width: 100%; +} +.tp-footer__list ul li a::after { + content: ""; + top: 50%; + left: 0; + width: 0%; + height: 1px; + background-color: var(--tp-common-purple); + position: absolute; + opacity: 0; + visibility: hidden; + transition: 0.3s; + transform: translateY(-50%); +} + +.footer-col-2 { + margin-left: 50px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .footer-col-2 { + margin-left: 0; + } +} + +.footer-col-3 { + margin-left: 100px; +} +@media only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .footer-col-3 { + margin-left: 0; + } +} + +.tp-copyright__border { + border-top: 1px solid #DFDFEA; + padding: 21px 0; +} + +.tp-copyright__text { + margin-left: -45px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px), only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px), (max-width: 767px) { + .tp-copyright__text { + margin-left: 0; + } +} +.tp-copyright__text span { + font-weight: 500; + font-size: 16px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-copyright__text span { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .tp-copyright__text span { + font-size: 14px; + } +} +@media (max-width: 767px) { + .tp-copyright__text span { + font-size: 13px; + } +} +.tp-copyright__text span i { + font-style: normal; + color: var(--tp-common-black); +} +.tp-copyright__text a { + font-weight: 500; + font-size: 16px; +} +@media only screen and (min-width: 1200px) and (max-width: 1399px) { + .tp-copyright__text a { + font-size: 15px; + } +} +@media only screen and (min-width: 992px) and (max-width: 1199px), only screen and (min-width: 768px) and (max-width: 991px) { + .tp-copyright__text a { + font-size: 14px; + } +} +@media (max-width: 767px) { + .tp-copyright__text a { + font-size: 13px; + } +} +.tp-copyright__text a i { + font-style: normal; + color: var(--tp-common-black); +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/1-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/1-img.svg new file mode 100644 index 00000000000..83f4e276480 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/1-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/2-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/2-img.svg new file mode 100644 index 00000000000..53232b20413 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/2-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/3-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/3-img.svg new file mode 100644 index 00000000000..71dfa308b8e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/3-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/4-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/4-img.svg new file mode 100644 index 00000000000..4debe4cac54 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/4-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/5-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/5-img.svg new file mode 100644 index 00000000000..d8b05aeb71e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/5-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/6-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/6-img.svg new file mode 100644 index 00000000000..0e5b07dcfa1 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/6-img.svg @@ -0,0 +1 @@ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand.svg new file mode 100644 index 00000000000..7525f3a828d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand_white.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand_white.svg new file mode 100644 index 00000000000..feae3b715d0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/brand_white.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/breadcrumb.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/breadcrumb.svg new file mode 100644 index 00000000000..ee3f992c0ed --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/breadcrumb.svg @@ -0,0 +1,226 @@ + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/cancel-star.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/cancel-star.svg new file mode 100644 index 00000000000..8a78fcec65a --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/cancel-star.svg @@ -0,0 +1,24 @@ + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/circle.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/circle.svg new file mode 100644 index 00000000000..3f4aa63304d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/circle.svg @@ -0,0 +1,1463 @@ + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/detail.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/detail.svg new file mode 100644 index 00000000000..21282d4f383 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/detail.svg @@ -0,0 +1,36 @@ + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/download.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/download.svg new file mode 100644 index 00000000000..97dea676c2c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/download.svg @@ -0,0 +1,40 @@ + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/email.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/email.svg new file mode 100644 index 00000000000..89d3f43d7bd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/email.svg @@ -0,0 +1,34 @@ + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/github.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/github.svg new file mode 100644 index 00000000000..990f302f291 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/github.svg @@ -0,0 +1,34 @@ + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/hand.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/hand.svg new file mode 100644 index 00000000000..9c0fd0d4704 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/hand.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-1.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-1.svg new file mode 100644 index 00000000000..de34b1dc513 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-1.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-2.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-2.svg new file mode 100644 index 00000000000..62c01bdca1c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-2.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-3.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-3.svg new file mode 100644 index 00000000000..f5f860a1910 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-3.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-page-bg.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-page-bg.svg new file mode 100644 index 00000000000..41ba031d32e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/home-page-bg.svg @@ -0,0 +1,1657 @@ + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/i18n.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/i18n.svg new file mode 100644 index 00000000000..a499deaf9e5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/i18n.svg @@ -0,0 +1,51 @@ + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo.svg new file mode 100644 index 00000000000..33a4012a9f0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo_white.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo_white.svg new file mode 100644 index 00000000000..14f3b138203 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/logo_white.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/mysql-img.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/mysql-img.svg new file mode 100644 index 00000000000..d67c845ac9e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/mysql-img.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/star.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/star.svg new file mode 100644 index 00000000000..c7a85d0f348 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/star.svg @@ -0,0 +1,24 @@ + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/title-line.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/title-line.svg new file mode 100644 index 00000000000..36f5f22cdb5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/title-line.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/upload-bg.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/upload-bg.svg new file mode 100644 index 00000000000..e2dde9430ae --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/upload-bg.svg @@ -0,0 +1,1598 @@ + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/user-center.svg b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/user-center.svg new file mode 100644 index 00000000000..47a054a1dfc --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/assets/svg/user-center.svg @@ -0,0 +1,40 @@ + + + + + + + + + + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.prod.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.prod.ts new file mode 100644 index 00000000000..ff182733454 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.prod.ts @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { Environment } from '@delon/theme'; + +export const environment = { + production: true, + useHash: false, + api: { + baseUrl: 'http://localhost:8081/api/', + refreshTokenEnabled: true + } +} as Environment; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.ts new file mode 100644 index 00000000000..3851eec9ace --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/environments/environment.ts @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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`. +// The list of file replacements can be found in `angular.json`. + +import { Environment } from '@delon/theme'; + +export const environment = { + production: false, + useHash: false, + api: { + // baseUrl: 'http://localhost:1157/api/', + baseUrl: 'http://localhost:8080/api/', + refreshTokenEnabled: true + } +} as Environment; + +/* + * In development mode, to ignore zone related error stack frames such as + * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can + * import the following file, but please comment it out in production mode + * because it will have performance impact when throw error + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/favicon.ico b/template-marketplace/hertzbeat-template-hub-web-app/src/favicon.ico new file mode 100644 index 00000000000..7a6cba72e7a Binary files /dev/null and b/template-marketplace/hertzbeat-template-hub-web-app/src/favicon.ico differ diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/index.html b/template-marketplace/hertzbeat-template-hub-web-app/src/index.html new file mode 100644 index 00000000000..25ff540e608 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/index.html @@ -0,0 +1,42 @@ + + + + + + + HertzBeatTemplateHubWebApp + + + + + + + + + + + + + + + +
+ + diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/main.ts b/template-marketplace/hertzbeat-template-hub-web-app/src/main.ts new file mode 100644 index 00000000000..33e2351d0d2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/main.ts @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 {enableProdMode, EnvironmentInjector, Injector, PLATFORM_ID, runInInjectionContext} from '@angular/core'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {environment} from '@env/environment'; +import {appConfig} from './app/app.config'; +import {AppComponent} from './app/app.component'; +import {DOCUMENT} from "@angular/common"; +import {stepPreloader} from "@delon/theme"; + +const injector = Injector.create({ + providers: [ + { provide: PLATFORM_ID, useValue: 'browser' }, + { + provide: DOCUMENT, + useFactory: () => { + return document; + } + } + ] +}) as EnvironmentInjector; + +let preloaderDone!: () => void; +runInInjectionContext(injector, () => (preloaderDone = stepPreloader())); +preloaderDone(); + +if (environment.production) { + // console.log('生产模式启动',environment.api) + enableProdMode(); +}else { + // console.log('开发模式启动:',environment.api) +} + + +bootstrapApplication(AppComponent, appConfig) + .then(() => { + const win = window as any; + if (win && win.appBootstrap) { + win.appBootstrap(); + } + }) + .catch((err) => console.error(err)); diff --git a/template-marketplace/hertzbeat-template-hub-web-app/src/styles.css b/template-marketplace/hertzbeat-template-hub-web-app/src/styles.css new file mode 100644 index 00000000000..0578054316c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/src/styles.css @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 './assets/css/style.css'; +@import "ng-zorro-antd/ng-zorro-antd.css"; diff --git a/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.app.json b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.app.json new file mode 100644 index 00000000000..7d7c716d715 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.json b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.json new file mode 100644 index 00000000000..4cbe37e33e7 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, + "esModuleInterop": true, + "sourceMap": true, + "declaration": false, + "experimentalDecorators": true, + "moduleResolution": "bundler", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "lib": [ + "ES2022", + "dom" + ], + "paths": { + "@shared": [ + "src/app/shared/index" + ], + "@core": [ + "src/app/core/index" + ], + "@env/*": [ + "src/environments/*" + ] + } + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.spec.json b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.spec.json new file mode 100644 index 00000000000..b18619fdfb5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub-web-app/tsconfig.spec.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/template-marketplace/hertzbeat-template-hub/.gitignore b/template-marketplace/hertzbeat-template-hub/.gitignore new file mode 100644 index 00000000000..549e00a2a96 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/template-marketplace/hertzbeat-template-hub/README.md b/template-marketplace/hertzbeat-template-hub/README.md new file mode 100644 index 00000000000..b1160ee28c6 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/README.md @@ -0,0 +1,2 @@ +## 🛡️ License +[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html) diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/category.http b/template-marketplace/hertzbeat-template-hub/apiTest/category.http new file mode 100644 index 00000000000..b69960fe0bf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/category.http @@ -0,0 +1,38 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### add category +POST http://localhost:8080/api/category/upload/test +Content-Type: application/x-www-form-urlencoded + +description=test + +### modify category +POST http://localhost:8080/api/category/modify/1 +Content-Type: application/x-www-form-urlencoded + +name=Database monitoring& +description=数据库监控模版 + +### delete category +DELETE http://localhost:8080/api/category/delete/1 + +### get category by isDel +GET http://localhost:8080/api/category/all/0 + +### get category page by isDel +GET http://localhost:8080/api/category/page/isDel/0?page=0&size=10 \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/share.http b/template-marketplace/hertzbeat-template-hub/apiTest/share.http new file mode 100644 index 00000000000..cced4472d49 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/share.http @@ -0,0 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### share +GET http://localhost:8080/api/share/getShareURL/1 + +### downloadShare +GET http://localhost:8080/api/share/download/6laZF \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/star.http b/template-marketplace/hertzbeat-template-hub/apiTest/star.http new file mode 100644 index 00000000000..b819317d9f4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/star.http @@ -0,0 +1,39 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### get starDO templateDO id by user +GET http://localhost:8080/api/starDO/1 + +### assert templateDO is starDO by user +GET http://localhost:8080/api/starDO/isStar/1/1 + +### starDO versionDO +POST http://localhost:8080/api/templateDO/starDO +Content-Type: application/x-www-form-urlencoded + + user=1& + templateDO=3 + +### get starDO templateDO page by user +GET http://localhost:8080/api/starDO/page/user/1?page=0&size=10 + +### cancel starDO +POST http://localhost:8080/api/starDO/cancel/1 +Content-Type: application/x-www-form-urlencoded + + templateId = 1 + diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/template.http b/template-marketplace/hertzbeat-template-hub/apiTest/template.http new file mode 100644 index 00000000000..2246d8887e5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/template.http @@ -0,0 +1,56 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### Get Count +GET http://localhost:8080/api/template/count/0/0 +Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eJwtzM0KwjAQBOB32XMj-Wua9OR7iEjTbCBqm5JtVRDf3VS8Dd8M84brmqAH5by2Y2yZsjYyzWPHnPGBWeetDyM6FwU0QJuv46cnyaU-CqMOY56qJ6LqtBWckYit-YYzIywPLHs7rNCLTjqtjGlVA_ha_qC53KHkO9aH0y9chjClGc6fL9mALgA.59te86AOUF0aAHZG_6pWTw5HM5DqBpk48QeOoZ_XSbINJVIy1lllgnaLOyvrDoKpVyozMMfaIoRWayFQD2SKUg + +### Get templates By user +GET http://localhost:8080/api/template/1 + +### Get templates Page By user +GET http://localhost:8080/api/template/page/user/1?page=0&size=10 + +### Get templates By category +GET http://localhost:8080/api/template/category/1 + +### Get templates Page By category +GET http://localhost:8080/api/template/page/category/1_3/0/1/1?page=0&size=2 + +### Get templates Page +GET http://localhost:8080/api/template/page/0/1?page=0&size=10 + +### Get templates order by order +GET http://localhost:8080/api/template/query/3/0 + +### Get templates Page By option +GET http://localhost:8080/api/template/page/option/My/1_3/0/1/1?page=0&size=10 + +### Get all templates noToken +GET http://localhost:8080/api/template/ + +### Authorization Get all templates +GET http://localhost:8080/api/template/ +Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eJw1zMEKwjAQBNB_2XMjSbokTU_-h4gk7QpRm0g2VUH8d1PB2_BmmDdcaoQRDIXZeScF4nkQaJwRXgUvUCrrrCI3TB464DW08TOwlhr3yvS7KS_NI3NzXgslYhY1XykJpvKgsrW-wqisdogae9UBve5_MHKDkm_UHg6_cPLzEhMcP1-hvS19.D9WYp53dXBrDd0MphrLhuipHmAbnd5ahuyHQkDkIFO28TRvYqGRGmY5l2vU26WpplVA81QHHl8DMQ9aFxXARAg + +### download +GET http://localhost:8080/api/template/download/1/1/v1.0.0/1 + +### download latest +GET http://localhost:8080/api/template/download/latest/1/1/1 \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/user.http b/template-marketplace/hertzbeat-template-hub/apiTest/user.http new file mode 100644 index 00000000000..d9ed12da7ab --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/user.http @@ -0,0 +1,44 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### Registy +POST http://localhost:8080/api/auth/register +Content-Type: application/json + +{ + "type": 1, + "identifier": "wbs2024@163.com", + "credential": "123456" +} + +### login+refresh +POST http://localhost:8080/api/auth/login +Content-Type: application/json + +{ + "type": 1, + "identifier": "wbs2024@163.com", + "credential": "123456" +} + +### refresh +POST http://localhost:8080/api/auth/refresh +Content-Type: application/json + +{ + "token": "eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eJwlyk0OwiAQQOG7zLpj-Kd01auATGM1toYBNTHeXRq333sfuNYVJogkvcnBYaCc0Ui3YLRJIUXrZdSjcCLBANxSn1-JlVBmlk6fzvu9-8rcnVuhjZix7jfakKk8qRw1VpikV8Fo7Z0dgN6PP1gzhgMKLYX4AlMtjb4_bgorXA.oYH8rk5Gb984ZcwBL-_N-6NcUk1githHwsKaQFxOewhne708JIsOhh6El3oKXE73gkEr5elASjUnL8zBzsVJ9A" +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/apiTest/version.http b/template-marketplace/hertzbeat-template-hub/apiTest/version.http new file mode 100644 index 00000000000..251d11d6027 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/apiTest/version.http @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +### Get all versionDO information of a templateDO +GET http://localhost:8080/api/versionDO/versionDO/1 + +### Get all versionDO page of a templateDO +GET http://localhost:8080/api/versionDO/page/1/0?page=0&size=2 + +### Get versionDO information By ID +GET http://localhost:8080/api/versionDO/get/1 \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/pom.xml b/template-marketplace/hertzbeat-template-hub/pom.xml new file mode 100644 index 00000000000..11c4f9093ff --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/pom.xml @@ -0,0 +1,187 @@ + + + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.2 + + + org.apache.hertzbeat.templatehub + hertzbeat-template-hub + 0.0.1-SNAPSHOT + hertzbeat-template-hub + hertzbeat-template-hub + + + + + + + + + + + + + + + 17 + UTF-8 + UTF-8 + 3.3.2 + 1.2.23 + 8.3.0 + 3.5.7 + 3.5.7 + 8.4.3 + 3.14.0 + 1.1.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.mysql + mysql-connector-j + + + + com.alibaba + druid-spring-boot-starter + 1.2.23 + + + org.slf4j + slf4j-api + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + io.swagger.core.v3 + swagger-annotations + 2.2.22 + + + + org.apache.commons + commons-lang3 + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + org.junit.vintage + junit-vintage-engine + + + + + + org.projectlombok + lombok + + + + io.minio + minio + 8.5.11 + + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + + + org.junit.platform + junit-platform-launcher + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.vintage + junit-vintage-engine + test + + + + org.mockito + mockito-core + test + + + + org.springframework.boot + spring-boot-starter-validation + + + + + + + + + + com.usthe.sureness + spring-boot3-starter-sureness + 1.1.0 + + + + javax.servlet + javax.servlet-api + 3.1.0 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/template-marketplace/hertzbeat-template-hub/sql/auth_resource.sql b/template-marketplace/hertzbeat-template-hub/sql/auth_resource.sql new file mode 100644 index 00000000000..05b27503c04 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/auth_resource.sql @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +create table auth_resource +( + id bigint auto_increment + primary key, + name varchar(100) not null, + code varchar(100) not null, + method varchar(255) not null, + status int null, + type varchar(255) null, + uri varchar(255) not null, + description varchar(255) null, + gmt_create datetime(6) null, + gmt_update datetime(6) null, + check ((`status` >= 0) and (`status` <= 9)) +); + +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (1, 'test', 'test', 'GET', 1, 'template', '/**/*', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (2, 'post', 'post', 'POST', 1, 'post', '/**/*', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (3, 'auth', 'auth', 'POST', 9, 'auth', '/api/auth/**', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (4, 'get-template', 'get-template', 'GET', 9, 'template-get', '/api/template/**', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (5, 'get-category', 'get-category', 'GET', 9, 'category-get', '/api/category/**', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (6, 'get-version', 'get-version', 'GET', 9, 'version-get', '/api/version/**', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (7, 'get-share', 'get-share', 'GET', 9, 'share-get', '/api/share/**', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (8, 'post-local', 'post-local', 'POST', 9, 'local', '/api/template/localFileUpload', null, null, null); +INSERT INTO hertzbeat_template_hub.auth_resource (id, name, code, method, status, type, uri, description, gmt_create, gmt_update) VALUES (9, 'get-star', 'get-star', 'GET', 9, 'star', '/api/star/isStar/**', null, null, null); diff --git a/template-marketplace/hertzbeat-template-hub/sql/auth_role.sql b/template-marketplace/hertzbeat-template-hub/sql/auth_role.sql new file mode 100644 index 00000000000..3e8319489dd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/auth_role.sql @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table auth_role +( + id bigint auto_increment + primary key, + code varchar(100) not null, + description varchar(255) null, + gmt_create datetime(6) null, + gmt_update datetime(6) null, + name varchar(100) not null, + status int null, + check ((`status` >= 0) and (`status` <= 9)) +); + +INSERT INTO hertzbeat_template_hub.auth_role (id, code, description, gmt_create, gmt_update, name, status) VALUES (1, 'role_admin', null, null, null, 'admin role', 1); +INSERT INTO hertzbeat_template_hub.auth_role (id, code, description, gmt_create, gmt_update, name, status) VALUES (2, 'role_user', null, null, null, 'user role', 1); diff --git a/template-marketplace/hertzbeat-template-hub/sql/auth_role_resource_bind.sql b/template-marketplace/hertzbeat-template-hub/sql/auth_role_resource_bind.sql new file mode 100644 index 00000000000..9c6f7013abf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/auth_role_resource_bind.sql @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table auth_role_resource_bind +( + id bigint auto_increment + primary key, + gmt_create datetime(6) null, + gmt_update datetime(6) null, + resource_id bigint not null, + role_id bigint not null +); + +INSERT INTO hertzbeat_template_hub.auth_role_resource_bind (id, gmt_create, gmt_update, resource_id, role_id) VALUES (1, null, null, 1, 2); +INSERT INTO hertzbeat_template_hub.auth_role_resource_bind (id, gmt_create, gmt_update, resource_id, role_id) VALUES (2, null, null, 2, 2); diff --git a/template-marketplace/hertzbeat-template-hub/sql/auth_user.sql b/template-marketplace/hertzbeat-template-hub/sql/auth_user.sql new file mode 100644 index 00000000000..4a191ed0ddd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/auth_user.sql @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table auth_user +( + id bigint auto_increment + primary key, + name varchar(255) not null comment '用户名,允许重复,允许修改', + email varchar(255) not null comment '邮箱,允许修改,用于用户登录', + create_time varchar(255) not null comment '注册时间', + log_off_time varchar(255) not null comment '注销时间,未注销为0,注销为时间', + avatar varchar(255) null, + password varchar(100) not null, + salt varchar(255) null, + status int null, + update_time varchar(255) not null, + check ((`status` >= 0) and (`status` <= 4)) +); + +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (1, 'user', 'wang_bs@163.com', '2024-10-19 21:56:14', '0', null, '251BCA22DFFC1469D001144E680E27BB', 'j6rchp', 1, '2024-10-19 21:56:14'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (2, 'wbs2024@163.com', 'wbs2024@163.com', '2024-10-19 21:56:14', '0', null, '251BCA22DFFC1469D001144E680E27BB', 'j6rchp', 1, '2024-10-19 21:56:14'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (3, 'wang_bs2025@163.com', 'wang_bs2025@163.com', '2024-10-28 20:55:28', '0', null, '8890D5B40B55EEA106F70EE1444FDBE3', 'qkz6zl', 1, '2024-10-28 20:55:28'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (4, 'wang_bs2026@163.com', 'wang_bs2026@163.com', '2024-10-28 20:58:02', '0', null, 'A6E3522FAAEC63443D9D74897C1CF57A', 'mkokmc', 1, '2024-10-28 20:58:02'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (5, 'wang_bs2027@163.com', 'wang_bs2027@163.com', '2024-10-28 20:59:18', '0', null, '9CB428E52EFB187333C6EE278E294310', 'svzdjg', 1, '2024-10-28 20:59:18'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (6, 'wang_bs2028@163.com', 'wang_bs2028@163.com', '2024-10-28 21:00:01', '0', null, '75DA0A713E957714FA17331A7A0C3514', 'mfp2bq', 1, '2024-10-28 21:00:01'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (7, 'user', 'wang_bs2029@163.com', '2024-10-28 21:22:07', '0', null, '89DE72E193A941E88A2220E59DE94EA7', 's9iepv', 1, '2024-10-28 21:22:07'); +INSERT INTO hertzbeat_template_hub.auth_user (id, name, email, create_time, log_off_time, avatar, password, salt, status, update_time) VALUES (8, 'user', 'wang_bs8@163.com', '2024-10-28 21:28:13', '0', null, 'B5F8BF9F0D7BBA4669CE9D2C28F9BC9F', 'fqcw90', 1, '2024-10-28 21:28:13'); diff --git a/template-marketplace/hertzbeat-template-hub/sql/auth_user_role_bind.sql b/template-marketplace/hertzbeat-template-hub/sql/auth_user_role_bind.sql new file mode 100644 index 00000000000..1fa12e96ac8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/auth_user_role_bind.sql @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table auth_user_role_bind +( + id bigint auto_increment + primary key, + gmt_create datetime(6) null, + gmt_update datetime(6) null, + role_id bigint not null, + user_id bigint not null +); + +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (1, null, null, 2, 1); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (2, null, null, 2, 2); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (3, null, null, 2, 3); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (4, null, null, 2, 4); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (5, null, null, 2, 5); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (6, null, null, 2, 6); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (7, null, null, 2, 7); +INSERT INTO hertzbeat_template_hub.auth_user_role_bind (id, gmt_create, gmt_update, role_id, user_id) VALUES (8, null, null, 2, 8); diff --git a/template-marketplace/hertzbeat-template-hub/sql/category.sql b/template-marketplace/hertzbeat-template-hub/sql/category.sql new file mode 100644 index 00000000000..e7b17700ddf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/category.sql @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table category +( + id int auto_increment comment '类别id' + primary key, + name varchar(255) not null comment '类别名', + description varchar(255) not null comment '描述', + create_time varchar(255) not null, + update_time varchar(255) not null comment '更新时间', + is_del int not null comment '删除标记' +); + +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (1, 'Database monitoring', '数据库监控模版', '2024-09-20 16:35:01', '2024-09-20 17:10:24', 0); +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (2, 'Application service monitoring', '应用服务监控模版', '2024-09-20 16:36:59', '2024-09-20 16:36:59', 0); +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (3, 'Operating system monitoring', '操作系统监控模版', '2024-09-20 16:37:51', '2024-09-20 16:37:51', 0); +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (4, 'Middleware monitoring', '中间件监控模版', '2024-09-20 16:38:11', '2024-09-20 16:38:11', 0); +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (5, 'CloudNative monitoring', '云原生监控模版', '2024-09-20 16:38:31', '2024-09-20 16:38:31', 0); +INSERT INTO hertzbeat_template_hub.category (id, name, description, create_time, update_time, is_del) VALUES (6, 'Network monitoring', '网络监控模版', '2024-09-20 16:38:54', '2024-09-20 16:38:54', 0); diff --git a/template-marketplace/hertzbeat-template-hub/sql/star.sql b/template-marketplace/hertzbeat-template-hub/sql/star.sql new file mode 100644 index 00000000000..6b9cab5c345 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/star.sql @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table star +( + id int auto_increment comment '收藏id' + primary key, + user_id int not null comment '用户id', + template_id int not null comment '模版id', + create_time varchar(255) not null, + is_del int not null comment '取消标记,0为正常,1为取消' +); diff --git a/template-marketplace/hertzbeat-template-hub/sql/tag.sql b/template-marketplace/hertzbeat-template-hub/sql/tag.sql new file mode 100644 index 00000000000..1b5cec572eb --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/tag.sql @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table tag +( + id int not null comment 'tagid' + primary key, + name varchar(255) not null comment 'tag名,不允许重复,允许修改', + description varchar(255) not null comment '描述', + create_time varchar(255) not null comment '创建时间', + is_del int not null comment '删除标记' +); + diff --git a/template-marketplace/hertzbeat-template-hub/sql/template.sql b/template-marketplace/hertzbeat-template-hub/sql/template.sql new file mode 100644 index 00000000000..feac47eb617 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/template.sql @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table template +( + id int auto_increment + primary key, + name varchar(255) not null comment '模版名,不允许修改,不同用户间可以重复', + description varchar(255) not null comment '模版描述', + latest int not null comment '最终版本id', + user int not null comment '用户id', + category_id int not null comment '模版类别id', + tag int not null comment '模版-tag表id,这个字段废弃,查询tag时直接去关联表中查询即可', + download int not null comment '下载量', + create_time varchar(255) not null comment '创建时间', + update_time varchar(255) not null comment '更新时间', + off_shelf int not null comment '下架标记,0为正常,1为下架', + is_del int not null comment '删除标记,0为正常,1为删除', + star int not null +); + +create index name_user_idx + on template (name, user) + comment '模版名+用户id的联合索引'; + +create index user_idx + on template (user); + +create index user_isDel_idx + on template (user, is_del); diff --git a/template-marketplace/hertzbeat-template-hub/sql/template_tag.sql b/template-marketplace/hertzbeat-template-hub/sql/template_tag.sql new file mode 100644 index 00000000000..9fcdf1b4c58 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/template_tag.sql @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table template_tag +( + id int not null comment 'template-tag id' + primary key, + template int not null comment 'template id', + tag int not null comment 'tag id' +); + diff --git a/template-marketplace/hertzbeat-template-hub/sql/version.sql b/template-marketplace/hertzbeat-template-hub/sql/version.sql new file mode 100644 index 00000000000..f664c312b4d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/sql/version.sql @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +create table version +( + id int auto_increment comment '版本id' + primary key, + template_id int not null comment '模版id', + version varchar(255) not null comment '版本号,不允许修改', + description varchar(255) not null comment '版本描述,todo:扩展为markdown文件地址', + download int not null comment '下载量', + create_time varchar(255) not null comment '创建时间', + off_shelf int not null comment '是否下架', + is_del int not null comment '是否删除', + star int not null +) + comment '版本表存放存储于minio中的object关键字信息,用用户名+template_id+版本号拼接,如果用户名允许修改或重复,则用用户id拼接'; + +create index template_isDel_idx + on version (template_id, is_del); + +create index template_version_idx + on version (template_id, version) + comment '通过该索引能够确定唯一数据'; \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplication.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplication.java new file mode 100644 index 00000000000..f57f0a5c03d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplication.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +@EnableTransactionManagement +public class HertzbeatTemplateHubApplication { + + public static void main(String[] args) { + SpringApplication.run(HertzbeatTemplateHubApplication.class, args); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/config/FileStorageConfig.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/config/FileStorageConfig.java new file mode 100644 index 00000000000..0a10a8b9329 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/config/FileStorageConfig.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.config; + +import org.apache.hertzbeat.templatehub.service.FileStorageService; +import org.apache.hertzbeat.templatehub.service.impl.LocalFileStorageServiceImpl; +import org.apache.hertzbeat.templatehub.service.impl.MinIOFileStorageServiceImpl; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FileStorageConfig { + + @Value("${file.storage.type}") + private String storageType; + + @Value("${minio.endpoint}") + private String minioEndpoint; + + @Value("${minio.accessKey}") + private String accessKey; + + @Value("${minio.secretKey}") + private String secretKey; + + @Bean + public FileStorageService fileStorageService() { + if ("minio".equalsIgnoreCase(storageType)) { + return new MinIOFileStorageServiceImpl( + minioEndpoint, + accessKey, + secretKey + ); + } else if ("local".equalsIgnoreCase(storageType)) { + return new LocalFileStorageServiceImpl(); + } else { + throw new IllegalArgumentException("Invalid file storage type: " + storageType); + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/constants/CommonConstants.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/constants/CommonConstants.java new file mode 100644 index 00000000000..5c20878d4fd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/constants/CommonConstants.java @@ -0,0 +1,375 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.constants; + +/** + * Public Common Constant + */ +public interface CommonConstants { + + /** + * Response status code: generic success + */ + byte SUCCESS_CODE = 0x00; + + /** + * Response status code: generic failure + */ + byte FAIL_CODE = 0x0F; + + /** + * Response status code: Incorrect login account password + */ + byte LOGIN_FAILED_CODE = 0x06; + + /** + * Response status code: Parameter verification failed + */ + byte PARAM_INVALID_CODE = 0x01; + + /** + * Response Status Code: Probe Failed + */ + byte DETECT_FAILED_CODE = 0x02; + + /** + * Response status code: monitoring does not exist + */ + byte MONITOR_NOT_EXIST_CODE = 0x03; + + /** + * Response Status Code: Monitor Service Conflict + */ + byte MONITOR_CONFLICT_CODE = 0x04; + + /** + * Response status code: Incorrect login account password + */ + byte MONITOR_LOGIN_FAILED_CODE = 0x05; + + /** + * Monitoring status 0: Paused, 1: Up, 2: Down + */ + byte MONITOR_PAUSED_CODE = 0x00; + + /** + * Monitoring status 0: Paused, 1: Up, 2: Down + */ + byte MONITOR_UP_CODE = 0x01; + + /** + * Monitoring status 0: Paused, 1: Up, 2: Down + */ + byte MONITOR_DOWN_CODE = 0x02; + + /** + * Alarm status: 0 - normal alarm (to be processed) + */ + byte ALERT_STATUS_CODE_PENDING = 0x00; + + /** + * Alarm Status: 1 - Threshold triggered but not reached the number of alarms + */ + byte ALERT_STATUS_CODE_NOT_REACH = 0x01; + + /** + * Alarm Status: 2-Restore Alarm + */ + byte ALERT_STATUS_CODE_RESTORED = 0x02; + + /** + * Alert Status: 3-Handled + */ + byte ALERT_STATUS_CODE_SOLVED = 0x03; + + /** + * Alarm level: 0: high-emergency-emergency-red + */ + byte ALERT_PRIORITY_CODE_EMERGENCY = 0x00; + + /** + * Alarm severity: 1: medium-critical-critical alarm-orange + */ + byte ALERT_PRIORITY_CODE_CRITICAL = 0x01; + + /** + * Warning level: 2: low-warning-warning warning-yellow + */ + byte ALERT_PRIORITY_CODE_WARNING = 0x02; + + /** + * Field parameter type: number + */ + byte TYPE_NUMBER = 0; + + /** + * Field parameter type: String + */ + byte TYPE_STRING = 1; + + /** + * Field parameter type: encrypted string + */ + byte TYPE_SECRET = 2; + + /** + * Field parameter type: time + */ + byte TYPE_TIME = 3; + + /** + * Collection metric value: null placeholder for empty value + */ + String NULL_VALUE = " "; + + /** + * + */ + String PROM_TIME = "timestamp"; + + /** + * + */ + String PROM_VALUE = "value"; + + /** + * Monitor total availability metrics + */ + String AVAILABILITY = "availability"; + + /** + * Parameter Type Number + */ + byte PARAM_TYPE_NUMBER = 0; + + /** + * Parameter Type String + */ + byte PARAM_TYPE_STRING = 1; + + /** + * Parameter Type Password + */ + byte PARAM_TYPE_PASSWORD = 2; + + /** + * Parameter Type Map values + */ + byte PARAM_TYPE_MAP = 3; + + /** + * Parameter Type arrays values + */ + byte PARAM_TYPE_ARRAY = 4; + + /** + * Authentication type Account password + */ + byte AUTH_TYPE_PASSWORD = 1; + + /** + * Authentication type GitHub three-party login + */ + byte AUTH_TYPE_GITHUB = 2; + + /** + * Authentication type WeChat three-party login + */ + byte AUTH_TYPE_WEIXIN = 3; + + /** + * Authentication type GITEE three-party login + */ + byte AUTH_TYPE_GITEE = 5; + + /** + * Inside the tag: monitorId Monitor task ID + */ + String TAG_MONITOR_ID = "monitorId"; + + /** + * Inside the tag: monitorName Task name + */ + String TAG_MONITOR_NAME = "monitorName"; + + /** + * Inside the tag: monitorHost Task host + */ + String TAG_MONITOR_HOST = "monitorHost"; + + /** + * Inside the tag: policyId Alarm threshold rule ID + */ + String TAG_THRESHOLD_ID = "thresholdId"; + + /** + * Inside the tag: app Type of monitoring + */ + String TAG_MONITOR_APP = "app"; + + /** + * Inside the tag: metrics + */ + String TAG_METRICS = "metrics"; + + /** + * Inside the tag: metric + */ + String TAG_METRIC = "metric"; + + /** + * Inside the tag: code + */ + String TAG_CODE = "code"; + + /** + * notice_period type Type field, daily type + */ + int NOTICE_PERIOD_DAILY = 0; + + /** + * key is receiver.id, value is noticePeriod cache key prefix + */ + String RECEIVER_NOTICE_PERIOD_CACHE_PREFIX = "receiver_notice_period:"; + + /** + * cache key notice_rule + */ + String CACHE_NOTICE_RULE = "notice_rule"; + + /** + * cache key alert silence + */ + String CACHE_ALERT_SILENCE = "alert_silence"; + + /** + * cache key alert converge + */ + String CACHE_ALERT_CONVERGE = "alert_converge"; + + /** + * collector status online 0 + */ + byte COLLECTOR_STATUS_ONLINE = 0; + + /** + * collector status offline 1 + */ + byte COLLECTOR_STATUS_OFFLINE = 1; + + /** + * default main collector name + */ + String MAIN_COLLECTOR_NODE = "main-default-collector"; + + /** + * locale spilt + */ + String LOCALE_SEPARATOR = "_"; + + /** + * ignore label + * Handle situations where recovery alarms are not configured, but need to be used to change task state + */ + String IGNORE = "ignore"; + + /** + * collector mode public + */ + String MODE_PUBLIC = "public"; + + /** + * collector mode private + */ + String MODE_PRIVATE = "private"; + + /** + * collector auth failed message + */ + String COLLECTOR_AUTH_FAILED = "Auth Failed"; + + /** + * for prometheus task name prefix + */ + String PROMETHEUS_APP_PREFIX = "_prometheus_"; + + /** + * prometheus + */ + String PROMETHEUS = "prometheus"; + + /** + * status page component state normal + */ + byte STATUS_PAGE_COMPONENT_STATE_NORMAL = 0; + + /** + * status page component state abnormal + */ + byte STATUS_PAGE_COMPONENT_STATE_ABNORMAL = 1; + + /** + * status page component state unknown + */ + byte STATUS_PAGE_COMPONENT_STATE_UNKNOWN = 2; + + /** + * status page org state all normal + */ + byte STATUS_PAGE_ORG_STATE_ALL_NORMAL = 0; + + /** + * status page org state some abnormal + */ + byte STATUS_PAGE_ORG_STATE_SOME_ABNORMAL = 1; + + /** + * status page org state all abnormal + */ + byte STATUS_PAGE_ORG_STATE_ALL_ABNORMAL = 2; + + /** + * status page component calculate method auto + */ + byte STATUE_PAGE_CALCULATE_METHOD_AUTO = 0; + + /** + * status page component calculate method manual + */ + byte STATUS_PAGE_CALCULATE_METHOD_MANUAL = 1; + + /** + * status page incident state investigating + */ + byte STATUS_PAGE_INCIDENT_STATE_INVESTIGATING = 0; + + /** + * status page incident state identified + */ + byte STATUS_PAGE_INCIDENT_STATE_IDENTIFIED = 1; + + /** + * status page incident state monitoring + */ + byte STATUS_PAGE_INCIDENT_STATE_MONITORING = 2; + + /** + * status page incident state resolved + */ + byte STATUS_PAGE_INCIDENT_STATE_RESOLVED = 3; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/AccountController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/AccountController.java new file mode 100644 index 00000000000..51aa3dd0580 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/AccountController.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import com.usthe.sureness.util.JsonWebTokenUtil; +import io.jsonwebtoken.ExpiredJwtException; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.transaction.Transactional; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.exception.HertzbeatTemplateHubException; +import org.apache.hertzbeat.templatehub.model.DTO.*; +import org.apache.hertzbeat.templatehub.service.AccountService; +import org.apache.hertzbeat.templatehub.service.RoleService; +import org.apache.hertzbeat.templatehub.util.ResponseUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.naming.AuthenticationException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.LOGIN_FAILED_CODE; + +@RestController +@CrossOrigin(maxAge = 3600,origins = "*") +@RequestMapping("/auth") +@Slf4j +public class AccountController { + + @Autowired + private AccountService accountService; + + @Autowired + private RoleService roleService; + + private static final String TOKEN_SPLIT = "--"; + + @PostMapping("/login") + @Operation(summary = "Account password login to obtain associated user information", description = "Account password login to obtain associated user information") + public ResponseEntity>> authGetToken(@Valid @RequestBody LoginDto loginDto) { + return ResponseUtil.handle(() -> accountService.authGetToken(loginDto)); + } + + @PostMapping("/refresh") + @Operation(summary = "Use refresh TOKEN to re-acquire TOKEN", description = "Use refresh TOKEN to re-acquire TOKEN") + public ResponseEntity> refreshToken(@Valid @RequestBody TokenDto tokenDto) { + try { + return ResponseEntity.ok(Message.success(accountService.refreshToken(tokenDto.getToken()))); + } catch (AuthenticationException e) { + return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, e.getMessage())); + } catch (ExpiredJwtException expiredJwtException) { + log.warn("{}", expiredJwtException.getMessage()); + return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "Refresh Token Expired")); + } catch (Exception e) { + log.error("Exception occurred during token refresh: {}", e.getClass().getName(), e); + return ResponseEntity.ok(Message.fail(LOGIN_FAILED_CODE, "Refresh Token Error")); + } + } + + @Deprecated + @PostMapping("/token") + public ResponseEntity>> issueJwtToken(@RequestBody @Validated LoginDto account) { + boolean authenticatedFlag = accountService.authenticateAccount(account); + if (!authenticatedFlag) { + Message> message = Message.fail(FAIL_CODE,"username or password not incorrect"); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(message); + } + List ownRole = accountService.loadAccountRoles(account.getIdentifier()); + String jwt = JsonWebTokenUtil.issueJwt(UUID.randomUUID().toString(), account.getIdentifier(), + "tom-auth-server", 3600L, ownRole); + Message> message = Message.success(Collections.singletonMap("token", jwt)); + return ResponseEntity.ok(message); + } + + @Deprecated + @PostMapping("/custom/token") + public ResponseEntity>> issueCustomToken(@RequestBody @Validated LoginDto account) { + boolean authenticatedFlag = accountService.authenticateAccount(account); + if (!authenticatedFlag) { + Message> message = Message.fail(FAIL_CODE,"username or password not incorrect"); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(message); + } + long refreshPeriodTime = 36000L; + String token = account.getIdentifier() + TOKEN_SPLIT + System.currentTimeMillis() + + TOKEN_SPLIT + refreshPeriodTime + + TOKEN_SPLIT + UUID.randomUUID().toString().replace("-", ""); + TokenStorage.addToken(account.getIdentifier(), token); + Map responseData = Collections.singletonMap("customToken", token); + Message> message = Message.success(responseData); + return ResponseEntity.status(HttpStatus.CREATED).body(message); + } + + @PostMapping("/register") + @Transactional + public ResponseEntity> accountRegister(@RequestBody @Validated SignUpDto account) { + //此处先让前端传递明文密码,后续改为加密密码 + + if (accountService.registerAccount(account)) { + Long authUser = roleService.getRoleIdByCode("role_user"); + if(authUser == null) throw new HertzbeatTemplateHubException("Role query error"); + boolean b = accountService.authorityUserRole(account.getEmail(), authUser); + if(!b) throw new HertzbeatTemplateHubException("Role authority error"); + Message message=Message.success("Sign up success, login after"); + if (log.isDebugEnabled()) { + log.debug("account: {}, sign up success", account); + } + return ResponseEntity.ok(message); + } else { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Email already exist")); + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/CategoryController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/CategoryController.java new file mode 100644 index 00000000000..059e0fd1d54 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/CategoryController.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.DO.CategoryDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.apache.hertzbeat.templatehub.service.CategoryService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping("category") +public class CategoryController { + + @Autowired + private CategoryService categoryService; + + @PostMapping("/upload/{name}") + public ResponseEntity> addCategory(@PathVariable("name") String name, + @RequestParam("description") String description) { + + if (name.isEmpty() || description.isEmpty()) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + } + + String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + boolean isOK = categoryService.addCategory(name, description, nowTime); + + if(!isOK){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"add category failed")); + } + return ResponseEntity.ok(Message.success("add category success")); + } + + @PostMapping("/modify/{id}") + public ResponseEntity> modifyCategory(@PathVariable("id") int id, + @RequestParam("name") String name, + @RequestParam("description") String description) { + + if (id<=0 || name.isEmpty() || description.isEmpty()) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + } + + String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + boolean isOK = categoryService.modifyCategory(id, name, description, nowTime); + + if(!isOK){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"modify category failed")); + } + return ResponseEntity.ok(Message.success("modify category success")); + } + + @DeleteMapping("/delete/{id}") + public ResponseEntity> deleteCategory(@PathVariable("id") int id) { + + if (id<=0) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"empty id")); + } + + boolean isOK = categoryService.deleteCategory(id); + + if(!isOK){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"category is used")); + } + return ResponseEntity.ok(Message.success("delete category success")); + } + + @GetMapping("/all/{isDel}") + public ResponseEntity>> getAllCategory(@PathVariable("isDel") int isDel) { + + if (isDel!=0&&isDel!=1) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"error option")); + } + + List allCategoryDOByIsDel = categoryService.getAllCategoryByIsDel(isDel); + + return ResponseEntity.ok(Message.success(allCategoryDOByIsDel)); + } + + @GetMapping("/page/isDel/{isDel}") + public ResponseEntity>> getCategoryPageByIsDel(@PathVariable("isDel") int isDel, @RequestParam int page, @RequestParam int size) { + + if (isDel!=0&&isDel!=1||page<0||size<0) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + } + + Page allCategoryByIsDel = categoryService.getPageByIsDel(isDel, page, size); + + return ResponseEntity.ok(Message.success(allCategoryByIsDel)); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ResourceController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ResourceController.java new file mode 100644 index 00000000000..f372597924f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ResourceController.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import jakarta.validation.constraints.NotBlank; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.service.ResourceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * @author tomsun28 + * @date 00:24 2019-08-01 + */ +@RequestMapping("/resource") +@RestController +@Slf4j +public class ResourceController { + + @Autowired + private ResourceService resourceService; + + @PostMapping + public ResponseEntity addResource(@RequestBody @Validated AuthResourceDO authResource) { + if (resourceService.addResource(authResource)) { + if (log.isDebugEnabled()) { + log.debug("add resource success: {}", authResource); + } + return ResponseEntity.status(HttpStatus.CREATED).build(); + } else { + Message message = Message.builder().msg("resource already exist").build(); + return ResponseEntity.status(HttpStatus.CONFLICT).body(message); + } + } + + @PutMapping + public ResponseEntity updateResource(@RequestBody @Validated AuthResourceDO authResource) { + if (resourceService.updateResource(authResource)) { + if (log.isDebugEnabled()) { + log.debug("update resource success: {}", authResource); + } + return ResponseEntity.ok().build(); + } else { + Message message = Message.builder().msg("resource not exist").build(); + return ResponseEntity.status(HttpStatus.CONFLICT).body(message); + } + } + + @DeleteMapping("/{resourceId}") + public ResponseEntity deleteResource(@PathVariable @NotBlank Long resourceId ) { + if (resourceService.deleteResource(resourceId)) { + if (log.isDebugEnabled()) { + log.debug("delete resource success: {}", resourceId); + } + return ResponseEntity.ok().build(); + } else { + Message message = Message.builder().msg("delete resource fail, please try again later").build(); + log.error("delete resource fail: {}", resourceId); + return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(message); + } + } + + @GetMapping("/{currentPage}/{pageSize}") + public ResponseEntity getResource(@PathVariable Integer currentPage, @PathVariable Integer pageSize ) { + if (Objects.isNull(currentPage) || Objects.isNull(pageSize)) { + // no pageable + Optional> resourceListOptional = resourceService.getAllResource(); + if (resourceListOptional.isPresent()) { + Message message = Message.builder().data(resourceListOptional.get()).build(); + return ResponseEntity.ok().body(message); + } else { + Message message = Message.builder().data(new ArrayList<>(0)).build(); + return ResponseEntity.ok().body(message); + } + } else { + // pageable + Page resourcePage = resourceService.getPageResource(currentPage, pageSize); + Message message = Message.builder().data(resourcePage.get()).build(); + return ResponseEntity.ok().body(message); + } + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/RoleController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/RoleController.java new file mode 100644 index 00000000000..1c90ee27486 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/RoleController.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import jakarta.validation.constraints.NotBlank; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleDO; +import org.apache.hertzbeat.templatehub.service.RoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * @author tomsun28 + * @date 00:24 2019-08-01 + */ +@RestController +@RequestMapping("/role") +@Slf4j +public class RoleController { + + @Autowired + private RoleService roleService; + + + @GetMapping("/resource/{roleId}/{currentPage}/{pageSize}") + public ResponseEntity getResourceOwnByRole(@PathVariable @NotBlank Long roleId, @PathVariable Integer currentPage, @PathVariable Integer pageSize) { + if (currentPage == null){ + currentPage = 1; + } + if (pageSize == null) { + pageSize = 10; + } + Page resourcePage = roleService.getPageResourceOwnRole(roleId, currentPage, pageSize); + Message message = Message.builder().data(resourcePage).build(); + return ResponseEntity.ok().body(message); + } + + @GetMapping("/resource/-/{roleId}/{currentPage}/{pageSize}") + public ResponseEntity getResourceNotOwnByRole(@PathVariable @NotBlank Long roleId, @PathVariable Integer currentPage, @PathVariable Integer pageSize) { + if (currentPage == null){ + currentPage = 1; + } + if (pageSize == null) { + pageSize = 10; + } + Page resourcePage = roleService.getPageResourceNotOwnRole(roleId, currentPage, pageSize); + Message message = Message.builder().data(resourcePage).build(); + return ResponseEntity.ok().body(message); + } + + @PostMapping("/authority/resource/{roleId}/{resourceId}") + public ResponseEntity authorityRoleResource(@PathVariable @NotBlank Long roleId, + @PathVariable @NotBlank Long resourceId) { + roleService.authorityRoleResource(roleId,resourceId); + return ResponseEntity.status(HttpStatus.OK).build(); + } + + @DeleteMapping("/authority/resource/{roleId}/{resourceId}") + public ResponseEntity deleteAuthorityRoleResource(@PathVariable @NotBlank Long roleId, + @PathVariable @NotBlank Long resourceId) { + roleService.deleteAuthorityRoleResource(roleId,resourceId); + return ResponseEntity.status(HttpStatus.OK).build(); + } + + @PostMapping + public ResponseEntity addRole(@RequestBody @Validated AuthRoleDO authRole) { + if (roleService.addRole(authRole)) { + if (log.isDebugEnabled()) { + log.debug("add role success: {}", authRole); + } + return ResponseEntity.status(HttpStatus.CREATED).build(); + } else { + Message message = Message.builder() + .msg("role already exist").build(); + return ResponseEntity.status(HttpStatus.CONFLICT).body(message); + } + } + + @PutMapping + public ResponseEntity updateRole(@RequestBody @Validated AuthRoleDO authRole) { + if (roleService.updateRole(authRole)) { + if (log.isDebugEnabled()) { + log.debug("update role success: {}", authRole); + } + return ResponseEntity.ok().build(); + } else { + Message message = Message.builder() + .msg("role not exist").build(); + return ResponseEntity.status(HttpStatus.CONFLICT).body(message); + } + } + + @DeleteMapping("/{roleId}") + public ResponseEntity deleteRole(@PathVariable @NotBlank Long roleId) { + if (roleService.deleteRole(roleId)) { + if (log.isDebugEnabled()) { + log.debug("delete role success: {}", roleId); + } + return ResponseEntity.ok().build(); + } else { + Message message = Message.builder() + .msg("delete role fail, no this role here").build(); + log.debug("delete role fail: {}", roleId); + return ResponseEntity.status(HttpStatus.CONFLICT).body(message); + } + } + + @GetMapping("/{currentPage}/{pageSize}") + public ResponseEntity getRole(@PathVariable Integer currentPage, @PathVariable Integer pageSize ) { + if (Objects.isNull(currentPage) || Objects.isNull(pageSize)) { + // no pageable + Optional> roleListOptional = roleService.getAllRole(); + if (roleListOptional.isPresent()) { + Message message = Message.builder().data(roleListOptional.get()).build(); + return ResponseEntity.ok().body(message); + } else { + Message message = Message.builder().data(new ArrayList<>()).build(); + return ResponseEntity.ok().body(message); + } + } else { + // pageable + Page rolePage = roleService.getPageRole(currentPage, pageSize); + Message message = Message.builder().data(rolePage).build(); + return ResponseEntity.ok().body(message); + } + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ShareController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ShareController.java new file mode 100644 index 00000000000..c32d0df1ad0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/ShareController.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.apache.hertzbeat.templatehub.util.Base62Util; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@RestController +@RequestMapping("share") +@CrossOrigin(origins = "*") +public class ShareController { + + @Value("${server.address}") + private String serverAddress; + + @Value("${server.port}") + private String serverPort; + + @Value("${server.servlet.context-path}") + private String contextPath; + + @Autowired + TemplateService templateService; + @Autowired + VersionService versionService; + + @GetMapping("/getShareURL/{version}") + public ResponseEntity> getShareURL(@PathVariable("version") long versionId){ + + if(versionId<=0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + + VersionDO versionDO = versionService.getVersion((int) versionId); + if(versionDO ==null) return ResponseEntity.ok(Message.fail(FAIL_CODE,"version not found")); + + String base62Key = Base62Util.idToShortKey(versionId+100000000); + + return ResponseEntity.ok(Message.success("http://"+serverAddress+":"+serverPort+contextPath+"/share/download/"+base62Key)); + } + + @GetMapping("/download/{key}") + public ResponseEntity downloadShare(@PathVariable("key") String key){ + + if(!Base62Util.isBase62(key)) return ResponseEntity.notFound().build(); + + long versionId = (int) Base62Util.shortKeyToId(key)-100000000; + + VersionDO versionDO = versionService.getVersion((int) versionId); + + if(versionDO ==null) return ResponseEntity.notFound().build(); + + TemplateDO templateDO = templateService.getTemplate(versionDO.getTemplateId()); + + Resource resource = templateService.downloadTemplate(templateDO.getUser(), templateDO.getId(), versionDO.getVersion(), (int) versionId); + + if(resource!=null) return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=\"" + versionDO.getVersion() + ".yml\"").body(resource); + else return ResponseEntity.notFound().build(); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/StarController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/StarController.java new file mode 100644 index 00000000000..687bef16032 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/StarController.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.VO.TemplateVO; +import org.apache.hertzbeat.templatehub.service.StarService; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping("star") +public class StarController { + + @Autowired + private StarService starService; + + @Autowired + private VersionService versionService; + + @Autowired + private TemplateService templateService; + + @GetMapping("/{user}") + public ResponseEntity>> getAllTemplateIdByUserStar(@PathVariable("user") int userId){ + if(userId<=0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + + List templateByUserStar = starService.getTemplateByUserStar(userId, 0); + Collections.sort(templateByUserStar); + return ResponseEntity.ok(Message.success(templateByUserStar)); + } + + @GetMapping("/isStar/{user}/{templateId}") + public ResponseEntity> assertTemplateIdIsStarByUser(@PathVariable("user") int userId, + @PathVariable("templateId") int templateId){ + if(userId<=0||templateId<=0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + + Boolean b = starService.assertTemplateIdIsStarByUser(userId, templateId); + + return ResponseEntity.ok(Message.success(b)); + } + + @GetMapping("/page/user/{user}") + public ResponseEntity>> getTemplatePageByUserStar(@PathVariable("user") int userId, + @RequestParam(required = false) Integer page, + @RequestParam(required = false) Integer size){ + if(userId<=0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"User Error")); + } + + Page res = starService.getPageByUserStar(userId, 0, 0, 0,page,size); + List templateVOList = res.getContent() + .stream() + .map(templateDO -> new TemplateVO(templateDO,true)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), res.getTotalElements()))); + } + + @Transactional + @PostMapping("/cancel/{user}") + public ResponseEntity> cancelStar(@PathVariable("user") int userId, @RequestParam("templateId") int templateId){ + if(userId<=0||templateId<=0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + } + + boolean b=starService.assertTemplateIdIsStarByUser(userId, templateId); + if(!b){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Template is not star")); + } + + Boolean isOk = starService.cancelStarByUser(userId, templateId); + if(!isOk){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"cancel Error")); + } + + boolean isOk2 = templateService.cancelStarTemplate(templateId); + if(!isOk2){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"cancel Error")); + } + return ResponseEntity.ok(Message.success("cancel success")); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TagController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TagController.java new file mode 100644 index 00000000000..4d815a62dd2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TagController.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.apache.hertzbeat.templatehub.service.TagService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping("tag") +public class TagController { + + @Autowired + private TagService tagService; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateController.java new file mode 100644 index 00000000000..b5f2e7ab447 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateController.java @@ -0,0 +1,409 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.hertzbeat.templatehub.exception.HertzbeatTemplateHubException; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.apache.hertzbeat.templatehub.model.VO.TemplateVO; +import org.apache.hertzbeat.templatehub.service.StarService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.jetbrains.annotations.NotNull; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.multipart.MultipartFile; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@RestController +@CrossOrigin(origins = "*",maxAge = 3600) +@RequestMapping("template") +public class TemplateController { + + @Autowired + private TemplateService templateService; + + @Autowired + private VersionService versionService; + + @Autowired + private StarService starService; + + @PostMapping("/localFileUpload") + public ResponseEntity> localFileUpload(@RequestParam("file") MultipartFile file){ + + return ResponseEntity.ok(Message.success("ok")); + } + + @PostMapping("/upload") + public ResponseEntity> uploadTemplate(@ModelAttribute("templateDto") String s, + @RequestParam("file") MultipartFile file){ + if(file.isEmpty()||s==null || s.isEmpty()) return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + + ObjectMapper objectMapper = new ObjectMapper(); + TemplateDto templateDto; + try { + templateDto = objectMapper.readValue(s, TemplateDto.class); + } catch (JsonProcessingException e) { + return ResponseEntity.ok(Message.fail(FAIL_CODE, + "Template description information reading exception"+e.getMessage())); + } + templateDto.setCreate_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + templateDto.setUpdate_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + if(templateDto.getUserId()==0||templateDto.getName().isEmpty()||templateDto.getCurrentVersion().isEmpty()){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + } + + boolean upload = templateService.upload(templateDto, file); + if(upload) return ResponseEntity.ok(Message.success("upload success")); + return ResponseEntity.ok(Message.fail(FAIL_CODE,"upload fail")); + } + + @GetMapping("/count/{isDel}/{offShelf}") + public ResponseEntity> getCountByIsDelAndOffshelf(@PathVariable("isDel") int isDel, @PathVariable("offShelf") int offshelf){ + if(isDel<0 || offshelf<0 || isDel>1 || offshelf>1) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + int countByIsDelAndOffShelf = templateService.getCountByIsDelAndOffShelf(isDel, offshelf); + return ResponseEntity.ok(Message.success(countByIsDelAndOffShelf)); + } + + @GetMapping("/page/category/{categoryIdStr}/{isDel}/{orderOption}/{userId}") + public ResponseEntity>> getTemplatePageByCategory(@PathVariable("categoryIdStr") String categoryIdStr, @PathVariable("isDel") int isDel, + @PathVariable("orderOption") int orderOption, @PathVariable("userId") int userId, + @RequestParam int page, @RequestParam int size){ + String[] s = categoryIdStr.split("_"); + List categoryIdList=new ArrayList<>(); + for (String string : s) { + if (string.isEmpty()) continue; + int num; + try { + num = Integer.parseInt(string); + } catch (NumberFormatException e) { + continue; + } + if (num >= 0) categoryIdList.add(num); + } + + if(categoryIdList.isEmpty() ||page<0||size<0||orderOption<=0||isDel<0||isDel>1) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + Page templatesByCategory = templateService.getPageByCategory(categoryIdList,isDel,orderOption,page,size); + + if(userId==0){ + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, new ArrayList<>())) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + List templateIdsByUserStar = starService.getTemplateByUserStar(userId, 0); + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, templateIdsByUserStar)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + + @GetMapping("/page/option/{nameLike}/{categoryIdStr}/{isDel}/{orderOption}/{userId}") + public ResponseEntity>> getTemplatePageByOrder(@PathVariable("nameLike") String nameLike, @PathVariable("categoryIdStr") String categoryIdStr, + @PathVariable("isDel") int isDel, @PathVariable("orderOption") int orderOption, + @PathVariable("userId") int userId, @RequestParam int page, @RequestParam int size){ + List categoryIdList = getCategoryList(categoryIdStr); + + if(categoryIdList.isEmpty() ||page<0||size<0||orderOption<=0||isDel<0||isDel>1||userId<0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + Page templatesByCategory = templateService.getPageByOption(nameLike, categoryIdList, isDel, orderOption, page, size); + + if(userId==0){ + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, new ArrayList<>())) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + List templateIdsByUserStar = starService.getTemplateByUserStar(userId, 0); + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, templateIdsByUserStar)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + + @GetMapping("/page/order/{order}/{isDel}/{userId}") + public ResponseEntity>> getTemplatePageByOrder(@PathVariable("order") int order, @PathVariable("isDel") int isDel, + @PathVariable("userId") int userId, + @RequestParam int page, @RequestParam int size){ + + if(page<0||size<=0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + Page res=null; + if(order==1) res=templateService.getPageByIsDelOrderByCreateTimeAsc(isDel, page, size); + else if (order==2) res=templateService.getPageByIsDelOrderByCreateTimeDesc(isDel, page, size); + else if (order==3) res=templateService.getPageByIsDelOrderByDownloadAsc(isDel, page, size); + else if (order==4) res=templateService.getPageByIsDelOrderByDownloadDesc(isDel, page, size); + else if (order==5) res=templateService.getPageByIsDelOrderByUpdateTimeAsc(isDel, page, size); + else if (order==6) res=templateService.getPageByIsDelOrderByUpdateTimeDesc(isDel, page, size); + else if (order==7) res=templateService.getPageByIsDelOrderByStarAsc(isDel, page, size); + else if (order==8) res=templateService.getPageByIsDelOrderByStarDesc(isDel, page, size); + if(res==null) return getTemplatesByPage(isDel, userId, page, size); + + if(userId==0){ + List templateVOList = res.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, new ArrayList<>())) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), res.getTotalElements()))); + } + List templateIdsByUserStar = starService.getTemplateByUserStar(userId, 0); + List templateVOList = res.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, templateIdsByUserStar)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), res.getTotalElements()))); + } + + @GetMapping("/page/name/{name}/{isDel}/{orderOption}/{userId}") + public ResponseEntity>> getPageByName(@PathVariable("name") String name, @PathVariable("isDel") int isDel, + @PathVariable("orderOption") int orderOption, @PathVariable("userId") int userId, + @RequestParam int page, @RequestParam int size){ + if(page<0||size<=0||orderOption<=0||isDel<0||isDel>1||userId<0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + if(name.isEmpty()) return getTemplatePageByOrder(orderOption, isDel, userId, page, size); + Page templatesByCategory = templateService.getPageByNameLike(name,isDel,orderOption, page, size); + + if(userId==0){ + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, new ArrayList<>())) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + List templateIdsByUserStar = starService.getTemplateByUserStar(userId, 0); + List templateVOList = templatesByCategory.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, templateIdsByUserStar)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByCategory.getTotalElements()))); + } + + @GetMapping("/page/user/{user}") + public ResponseEntity>> getTemplatePageByUser(@PathVariable("user") int userId, @RequestParam int page, @RequestParam int size){ + if(userId==0||page<0||size<0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + Page templatePageByUserId = templateService.getPageByUserId(userId, page, size); + return ResponseEntity.ok(Message.success(templatePageByUserId)); + } + + @GetMapping("/page/{isDel}/{userId}") + public ResponseEntity>> getTemplatesByPage(@PathVariable("isDel") int isDel, + @PathVariable("userId") int userId, + @RequestParam int page, @RequestParam int size) { + if(isDel<0||isDel>1||page<0||size<=0||userId<0) return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + + Page templatesByPage = templateService.getTemplatesByPage(isDel, page, size); + if(userId==0){ +// Page templatesByPage = templateService.getTemplatesByPage(isDel, page, size); + List templateVOList = templatesByPage.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, new ArrayList<>())) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByPage.getTotalElements()))); + } + List templateIdsByUserStar = starService.getTemplateByUserStar(userId, 0); +// Page templatesByPage = templateService.getTemplatesByPage(isDel, page, size); + List templateVOList = templatesByPage.getContent() + .stream() + .map(templateDO -> convertToTemplateVO(templateDO, templateIdsByUserStar)) + .toList(); + return ResponseEntity.ok(Message.success(new PageImpl<>(templateVOList, PageRequest.of(page,size), templatesByPage.getTotalElements()))); + } + + private TemplateVO convertToTemplateVO(TemplateDO templateDO, List ids) { + + return new TemplateVO(templateDO,ids.contains(templateDO.getId())); + } + + @GetMapping("/download/{ownerId}/{templateId}/{version}/{versionId}") + public ResponseEntity download(@PathVariable("ownerId") Integer ownerId, @PathVariable("templateId") Integer templateId, + @PathVariable("version") String version, @PathVariable("versionId") Integer versionId) { + if (templateId == null || version == null || ownerId==null) throw new HertzbeatTemplateHubException("id empty"); + + Resource resource = templateService.downloadTemplate(ownerId, templateId, version, versionId); + if(resource!=null) return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + version + ".yml\"").body(resource); + else return ResponseEntity.notFound().build(); + } + + @GetMapping("/download/latest/{ownerId}/{templateId}/{versionId}") + public ResponseEntity downloadLatest(@PathVariable("ownerId") Integer ownerId, @PathVariable("templateId") Integer templateId, + @PathVariable("versionId") Integer versionId) { + if (templateId == null || ownerId==null) throw new HertzbeatTemplateHubException("params error"); + + VersionDO latestVersionDO = versionService.getLatestVersion(templateId); + if(latestVersionDO ==null) throw new HertzbeatTemplateHubException("no version found"); + + Resource resource = templateService.downloadTemplate(ownerId, templateId, latestVersionDO.getVersion(), versionId); + if(resource!=null) return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + latestVersionDO.getVersion() + ".yml\"").body(resource); + else return ResponseEntity.notFound().build(); + } + + @DeleteMapping("/delete/{ownerId}/{templateId}/{version}") + public ResponseEntity> deleteFile(@PathVariable("ownerId") Integer ownerId, @PathVariable("templateId") Integer templateId, @PathVariable("version") String version) { + if (templateId == null || version == null || ownerId==null) return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + + templateService.deleteTemplate(ownerId, templateId,version); + return ResponseEntity.ok(Message.success("delete success")); + } + + private static @NotNull List getCategoryList(String categoryIdStr) { + String[] categoryIdStrList = categoryIdStr.split("_"); + List categoryIdList=new ArrayList<>(); + for (String string : categoryIdStrList) { + if (string.isEmpty()) continue; + int num; + try { + num = Integer.parseInt(string); + } catch (NumberFormatException e) { + continue; + } + if (num >= 0) categoryIdList.add(num); + } + return categoryIdList; + } + + @GetMapping("/") + public ResponseEntity>> getAllTemplates(){ + + List allTemplates = templateService.getAllTemplates(); + return ResponseEntity.ok(Message.success(allTemplates)); + } + + @PostMapping("/star") + @Transactional + public ResponseEntity> starVersion(@RequestParam("user") int userId,@RequestParam("template") int templateId){ + + if(userId==0||templateId==0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + } + + boolean b = starService.assertTemplateIdIsStarByUser(userId, templateId); + if(b){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Already star template")); + } + + String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + int isOk = starService.starTemplate(userId, templateId, nowTime); + + if(isOk==0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"star template error")); + } + + boolean isOk3 = templateService.starTemplate(templateId); + if(!isOk3){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"star template error")); + } + + return ResponseEntity.ok(Message.success("star template success")); + } + +// @Deprecated +// @GetMapping("/query/{option}/{isDel}") +// public ResponseEntity>> getTemplateByOption(@PathVariable("option") int option, +// @PathVariable("isDel") int isDel){ +// if(option<=0||isDel<0||isDel>1){ +// return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); +// } +// List res=new ArrayList<>(); +// if(option==1){ +// res=templateService.getByIsDelOrderByCreateTimeAsc(isDel); +// } else if (option==2) { +// res=templateService.getByIsDelOrderByCreateTimeDesc(isDel); +// }else if (option==3) { +// res=templateService.getByIsDelOrderByDownloadAsc(isDel); +// }else if (option==4) { +// res=templateService.getByIsDelOrderByDownloadDesc(isDel); +// }else if (option==5) { +// res=templateService.getPageByIsDelOrderByUpdateTimeAsc(isDel); +// } else if (option==6) { +// res=templateService.getByIsDelOrderByUpdateTimeDesc(isDel); +// }else if (option==7) { +// res=templateService.getByIsDelOrderByStarAsc(isDel); +// }else if (option==8) { +// res=templateService.getByIsDelOrderByStarDesc(isDel); +// }else { +// return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); +// } +// if(res.isEmpty()){ +// return getAllTemplates(); +// } +// return ResponseEntity.ok(Message.success(res)); +// } +// +// @Deprecated +// @GetMapping("/{user}") +// public ResponseEntity>> getTemplateByUser(@PathVariable("user") int userId){ +// if(userId==0){ +// return ResponseEntity.ok(Message.fail(FAIL_CODE,"User Error")); +// } +// +// return templateService.getAllTemplatesByUserId(userId); +// } +// +// @Deprecated +// @GetMapping("/category/{categoryId}") +// public ResponseEntity>> getTemplateByCategory(@PathVariable("categoryId") int categoryId){ +// if(categoryId<=0){ +// return ResponseEntity.ok(Message.fail(FAIL_CODE,"Error category")); +// } +// +// List templatesByCategory = templateService.getTemplatesByCategory(categoryId); +// +// return ResponseEntity.ok(Message.success(templatesByCategory)); +// } +// +// @Deprecated +// @GetMapping("/name/{name}") +// public ResponseEntity>> getTemplateByName(@PathVariable("name") String name){ +// if(name.isEmpty()){ +// return getAllTemplates(); +// } +// +// List templatesByCategory = templateService.getTemplatesByNameLike(name); +// +// return ResponseEntity.ok(Message.success(templatesByCategory)); +// } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateTagController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateTagController.java new file mode 100644 index 00000000000..48cd63700b4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TemplateTagController.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.apache.hertzbeat.templatehub.service.TemplateTagService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping("templateTag") +public class TemplateTagController { + + @Autowired + private TemplateTagService templateTagService; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TokenStorage.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TokenStorage.java new file mode 100644 index 00000000000..b46b1fb090d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/TokenStorage.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * token storage + * you can use redis instead of it + * @author tomsun28 + * @date 2020-12-03 23:01 + */ +public class TokenStorage { + + private static final String TOKEN_SPLIT = "--"; + private static final int TOKEN_SPLIT_SIZE = 4; + private static final int START_TIME_INDEX = 1; + private static final int PERIOD_TIME_INDEX = 2; + + private static final Map TOKEN_MAP = new ConcurrentHashMap<>(); + + /** + * match token + * @param key key + * @param currentToken tokenValue is : admin--issueTime--refreshPeriodTime--uuid + * @return false when token not exist, not equals or Expired, else true + */ + public static boolean matchToken(String key, String currentToken) { + if (key == null || currentToken == null || "".equals(key) || "".equals(currentToken) + || currentToken.split(TOKEN_SPLIT).length != TOKEN_SPLIT_SIZE) { + return false; + } + String originToken = TOKEN_MAP.get(key); + if (originToken == null || !originToken.equals(currentToken)) { + removeToken(key); + return false; + } + String[] tokenArr = currentToken.split(TOKEN_SPLIT); + if (Long.parseLong(tokenArr[START_TIME_INDEX]) + Long.parseLong(tokenArr[PERIOD_TIME_INDEX]) + <= System.currentTimeMillis()) { + // token expired, remove it + removeToken(key); + return false; + } + return true; + } + + public static void removeToken(String key) { + if (key == null || "".equals(key)) { + return; + } + TOKEN_MAP.remove(key); + } + + public static void addToken(String key, String token) { + if (key == null || token == null || "".equals(key) || "".equals(token) + || token.split(TOKEN_SPLIT).length != TOKEN_SPLIT_SIZE) { + return; + } + TOKEN_MAP.put(key, token); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/UserController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/UserController.java new file mode 100644 index 00000000000..05c742fb314 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/UserController.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import com.usthe.sureness.subject.SubjectSum; +import com.usthe.sureness.util.SurenessContextHolder; +import io.jsonwebtoken.ExpiredJwtException; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DTO.LoginDto; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DTO.RefreshTokenResponse; +import org.apache.hertzbeat.templatehub.model.DTO.TokenDto; +import org.apache.hertzbeat.templatehub.service.AccountService; +import org.apache.hertzbeat.templatehub.util.ResponseUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.naming.AuthenticationException; +import java.util.List; +import java.util.Map; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.LOGIN_FAILED_CODE; + +@Slf4j +@RestController +@CrossOrigin(origins = "*") +@RequestMapping("user") +public class UserController { + + @Autowired + private AccountService accountService; + + @GetMapping("/role") + public ResponseEntity getUserRoles() { + SubjectSum subject = SurenessContextHolder.getBindSubject(); + if (subject == null || subject.getPrincipal() == null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + String appId = (String) subject.getPrincipal(); + List roles = accountService.loadAccountRoles(appId); + return ResponseEntity.ok(Message.builder().data(roles).build()); + } + + @PostMapping("/authority/role/{appId}/{roleId}") + public ResponseEntity authorityUserRole(@PathVariable String appId, @PathVariable Long roleId) { + SubjectSum subject = SurenessContextHolder.getBindSubject(); + if (subject == null || subject.getPrincipal() == null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + String principal = (String) subject.getPrincipal(); + if (!principal.equals(appId)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + boolean flag = accountService.authorityUserRole(appId, roleId); + return flag ? ResponseEntity.ok().build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + @DeleteMapping("/authority/role/{appId}/{roleId}") + public ResponseEntity deleteAuthorityUserRole(@PathVariable String appId, @PathVariable Long roleId) { + SubjectSum subject = SurenessContextHolder.getBindSubject(); + if (subject == null || subject.getPrincipal() == null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + String principal = (String) subject.getPrincipal(); + if (!principal.equals(appId)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + return accountService.deleteAuthorityUserRole(appId, roleId) ? + ResponseEntity.ok().build() : ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/VersionController.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/VersionController.java new file mode 100644 index 00000000000..fa3059bce52 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/controller/VersionController.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@RestController +@RequestMapping("version") +@CrossOrigin(origins = "*") +public class VersionController { + + @Autowired + private VersionService versionService; + + @Deprecated + @GetMapping("/version/{template}") + public ResponseEntity>> getVersionsByTemplate(@PathVariable("template") int templateId){ + + if(templateId==0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Template information error")); + } + + List versionDOS = versionService.getVersions(templateId); + + return ResponseEntity.ok(Message.success(versionDOS)); + } + + @GetMapping("/get/{versionId}") + public ResponseEntity> getVersionById(@PathVariable("versionId") int versionId){ + + if(versionId==0){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"params error")); + } + + VersionDO versionDO = versionService.getVersion(versionId); + if(versionDO ==null){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"version not found")); + } + return ResponseEntity.ok(Message.success(versionDO)); + } + + @GetMapping("/page/{template}/{isDel}") + public ResponseEntity>> getVersionPageByTemplate(@PathVariable("template") int templateId, + @PathVariable("isDel") int isDel, + @RequestParam int page, @RequestParam int size){ + + if(templateId==0|| page <0|| size <=0 || isDel<0 || isDel>1){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Params Error")); + } + Page versionPageByTemplate = versionService.getVersionPageByTemplate(templateId, isDel, page, size); + return ResponseEntity.ok(Message.success(versionPageByTemplate)); + } + + @PostMapping("/upload") + public ResponseEntity> uploadVersion(@ModelAttribute("templateDto") String s, + @RequestParam("file") MultipartFile file){ + if(file.isEmpty()) return ResponseEntity.ok(Message.fail(FAIL_CODE,"The version file is empty")); + + if(s==null || s.isEmpty()) return ResponseEntity.ok(Message.fail(FAIL_CODE,"version info is empty")); + + ObjectMapper objectMapper = new ObjectMapper(); + TemplateDto templateDto; + try { + templateDto = objectMapper.readValue(s, TemplateDto.class); + } catch (JsonProcessingException e) { + return ResponseEntity.ok(Message.fail(FAIL_CODE, + "Template description information reading exception"+e.getMessage())); + } + templateDto.setCreate_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + templateDto.setUpdate_time(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + if(templateDto.getUserId()==0||templateDto.getName().isEmpty()||templateDto.getCurrentVersion().isEmpty()){ + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Template description information is missing")); + } + + boolean upload = versionService.upload(templateDto, file); + if(upload) return ResponseEntity.ok(Message.success("upload success")); + return ResponseEntity.ok(Message.fail(FAIL_CODE,"Error uploading version")); + } +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/CommonError.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/CommonError.java new file mode 100644 index 00000000000..b10fbb6d94f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/CommonError.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@ToString +@AllArgsConstructor +@Getter +public enum CommonError { + UNKNOWN_ERROR("执行过程异常,请重试"), + PARAMS_ERROR("非法参数"), + OBJECT_ERROR("对象为空"), + QUERY_ERROR("查询结果为空"), + REQUEST_ERROR("请求参数为空"); + + private String errMsg; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/GlobalExceptionHandler.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000000..908289c9a1b --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/GlobalExceptionHandler.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.exception; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import static org.apache.hertzbeat.templatehub.constants.CommonConstants.FAIL_CODE; + +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + @ResponseBody + @ExceptionHandler(HertzbeatTemplateHubException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseEntity> customException(HertzbeatTemplateHubException e) { + log.error("系统异常:{}", e.getMessage(), e); + + String errMessage = e.getMessage(); + + return ResponseEntity.ok(Message.fail(FAIL_CODE,errMessage)); + } + + @ResponseBody + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseEntity> exception(Exception e) { + + log.error("系统异常:{}", e.getMessage(), e); + if (e.getMessage().equals("不允许访问")) { + return ResponseEntity.ok(Message.fail(FAIL_CODE,"您没有权限操作此功能")); + } + + return ResponseEntity.ok(Message.fail(FAIL_CODE,CommonError.UNKNOWN_ERROR.getErrMsg())); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/HertzbeatTemplateHubException.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/HertzbeatTemplateHubException.java new file mode 100644 index 00000000000..63522b2a073 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/HertzbeatTemplateHubException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.exception; + +public class HertzbeatTemplateHubException extends RuntimeException { + + private String errMsg; + + public HertzbeatTemplateHubException() { + } + + public HertzbeatTemplateHubException(String errMsg) { + super(errMsg); + this.errMsg = errMsg; + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/RestErrorResponse.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/RestErrorResponse.java new file mode 100644 index 00000000000..2f980ef7204 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/exception/RestErrorResponse.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.exception; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.ToString; + +import java.io.Serializable; + +@Data +@ToString +@AllArgsConstructor +public class RestErrorResponse implements Serializable { + + private String errMsg; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthResourceDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthResourceDO.java new file mode 100644 index 00000000000..e802dd7b16a --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthResourceDO.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; + +import java.time.LocalDateTime; + +/** + * resource entity + * @author tomsun28 + * @date 00:00 2019-07-26 + */ +@Entity +@Table(name = "auth_resource") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuthResourceDO { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank(message = "name can not null") + @Length(min = 3, max = 100, message = "name length in 3-100") + private String name; + + @NotBlank(message = "code can not null") + @Length(min = 3, max = 100, message = "code length in 3-100") + private String code; + + @NotBlank(message = "uri can not null") + private String uri; + + private String type; + + @NotBlank(message = "method can not null") + private String method; + + @Range(min = 0, max = 9, message = "1 enable, 9 disable") + private Integer status; + + private String description; + + private LocalDateTime gmtCreate; + + private LocalDateTime gmtUpdate; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleDO.java new file mode 100644 index 00000000000..6e42bdbe069 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleDO.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; + +import java.time.LocalDateTime; + +/** + * role entity + * @author tomsun28 + * @date 00:27 2019-07-27 + */ +@Entity +@Table(name = "auth_role") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuthRoleDO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank(message = "name can not null") + @Length(min = 3, max = 100, message = "name length in 3-100") + private String name; + + @NotBlank(message = "code can not null") + @Length(min = 3, max = 100, message = "code length in 3-100") + private String code; + + @Range(min = 0, max = 9, message = "1 enable, 9 disable") + private Integer status; + + private String description; + + private LocalDateTime gmtCreate; + + private LocalDateTime gmtUpdate; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleResourceBindDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleResourceBindDO.java new file mode 100644 index 00000000000..ec4c7656bcd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthRoleResourceBindDO.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * resource-role mapping entity + * @author tomsun28 + * @date 00:28 2019-07-27 + */ +@Entity +@Table(name = "auth_role_resource_bind") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuthRoleResourceBindDO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull(message = "roleId can not null") + private Long roleId; + + @NotNull(message = "resourceId can not null") + private Long resourceId; + + private LocalDateTime gmtCreate; + + private LocalDateTime gmtUpdate; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserDO.java new file mode 100644 index 00000000000..922738ef904 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserDO.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import lombok.*; +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.Range; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Builder +@Entity +@Table(name = "auth_user") +public class AuthUserDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + + @Column(nullable = false) + @Schema(description = "Username, can be repeated, can be modified") + private String name; + + @Column(nullable = false) + @Schema(description = "Email, can be modified, used for user login") + private String email; + + @NotBlank(message = "password can not null") + @Length(min = 3, max = 100, message = "password length in 3-100") + private String password; + + private String salt; + + private String avatar; + + @Range(min = 0, max = 4, message = "1 enable, 2 locked, 3 deleted, 4 illegal") + private Integer status; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false,name = "update_time") + private String updateTime; + + @Column(nullable = false,name = "log_off_time") + @Schema(description = "Logout time, if not logged out it is 0, if logged out it is time") + private String logOffTime; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserRoleBindDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserRoleBindDO.java new file mode 100644 index 00000000000..37752ae9895 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/AuthUserRoleBindDO.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * user-role mapping entity + * @author tomsun28 + * @date 00:30 2019-07-27 + */ +@Entity +@Table(name = "auth_user_role_bind") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class AuthUserRoleBindDO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull(message = "userId can not null") + private Long userId; + + @NotNull(message = "roleId can not null") + private Long roleId; + + private LocalDateTime gmtCreate; + + private LocalDateTime gmtUpdate; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/CategoryDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/CategoryDO.java new file mode 100644 index 00000000000..fcb5a704ff3 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/CategoryDO.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "category") +public class CategoryDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "Category Name") + private String name; + + @Column(nullable = false) + private String description; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false, name = "update_time") + private String updateTime; + + @Column(nullable = false,name = "is_del") + @Schema(description = "Delete Mark") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/StarDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/StarDO.java new file mode 100644 index 00000000000..43677cce263 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/StarDO.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Table(name = "star") +@Entity +public class StarDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "user_id",nullable = false) + private Integer userId; + + @Column(name = "template_id",nullable = false) + private Integer templateId; + + @Column(name = "create_time",nullable = false) + private String createTime; + + @Column(name = "is_del",nullable = false) + @Schema(description = "Cancel flag, 0 means normal, 1 means cancel") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TagDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TagDO.java new file mode 100644 index 00000000000..626b339eb1c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TagDO.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "tag") +public class TagDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Schema(description = "Tag name, no duplication allowed, modification allowed") + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String description; + + @Column(name = "create_time",nullable = false) + private String createTime; + + @Column(name = "is_del",nullable = false) + private Integer isDel; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateDO.java new file mode 100644 index 00000000000..310d609dd98 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateDO.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name="template") +public class TemplateDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id=1; + + @Column(nullable = false) + @Schema(description = "Template name, cannot be modified, but can be repeated") + private String name; + + @Column(nullable = false) + private String description; + + @Column(nullable = false) + @Schema(description = "Latest version id") + private Integer latest; + + @Column(nullable = false) + @Schema(description = "user id") + private Integer user; + + @Column(nullable = false,name = "category_id") + @Schema(description = "Template category id") + private Integer categoryId; + + @Column(nullable = false) + @Schema(description = "Template-tag table id") + private Integer tag; + + @Column(nullable = false) + @Schema(description = "Downloads") + private Integer download; + + @Column(nullable = false) + private Integer star; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false, name = "update_time") + private String updateTime; + + @Column(nullable = false,name="off_shelf") + @Schema(description = "Delisting mark, 0 means normal, 1 means delisting") + private Integer offShelf; + + @Column(nullable = false,name = "is_del") + @Schema(description = "Delete mark, 0 means normal, 1 means delete") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateTagDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateTagDO.java new file mode 100644 index 00000000000..5176fc82315 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/TemplateTagDO.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "template_tag") +public class TemplateTagDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "template id") + private Integer template; + + @Column(nullable = false) + @Schema(description = "tag id") + private Integer tag; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/VersionDO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/VersionDO.java new file mode 100644 index 00000000000..95e59b87f7c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/DO/VersionDO.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DO; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "version") +public class VersionDO implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false, name = "template_id") + @Schema(description = "template id") + private Integer templateId; + + @Column(nullable = false) + @Schema(description = "Version name, modification is not allowed") + private String version; + + + @Column(nullable = false) + @Schema(description = "Version description") + private String description; + + @Column(nullable = false) + private Integer download; + + @Column(nullable = false) + private Integer star; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false,name = "off_shelf") + private Integer offShelf; + + @Column(nullable = false,name = "is_del") + private Integer isDel; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/VO/TemplateVO.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/VO/TemplateVO.java new file mode 100644 index 00000000000..93553cec6b4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/VO/TemplateVO.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.VO; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; + +@Data +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class TemplateVO { + + private Integer id; + private String name; + private String description; + private Integer latest; + private Integer user; + private Integer categoryId; + private Integer tag; + private Integer download; + private Integer star; + private String createTime; + private String updateTime; + private Integer offShelf; + private Integer isDel; + private boolean starByNowUser =false; + + public TemplateVO(TemplateDO template, boolean isStarByNowUser) { + this.id = template.getId(); + this.name = template.getName(); + this.description = template.getDescription(); + this.latest = template.getLatest(); + this.user = template.getUser(); + this.categoryId = template.getCategoryId(); + this.tag = template.getTag(); + this.download = template.getDownload(); + this.star = template.getStar(); + this.createTime = template.getCreateTime(); + this.updateTime = template.getUpdateTime(); + this.offShelf = template.getOffShelf(); + this.isDel = template.getIsDel(); + this.starByNowUser = isStarByNowUser; + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthResourceDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthResourceDao.java new file mode 100644 index 00000000000..e64fd582580 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthResourceDao.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +/** + * @author tomsun28 + * @date 16:40 2019-07-27 + */ +public interface AuthResourceDao extends JpaRepository { + + /** + * Get uri resource and resource-role relationship chain, eg: /api/v2/host===post===[role2,role3,role4] + * @return resource-role chain set + */ + @Query(value = "SELECT CONCAT(LOWER(res.uri),\"===\",LOWER(res.method),\"===[\",IFNULL(GROUP_CONCAT(DISTINCT role.code),\"\"),\"]\") " + + "FROM auth_resource res " + + "LEFT JOIN auth_role_resource_bind bind on res.id = bind.resource_id " + + "LEFT JOIN auth_role role on role.id = bind.role_id " + + "where res.status = 1 " + + "group by res.id", nativeQuery = true) + Optional> getEnableResourcePathRoleData(); + + + + /** + * Get disabled uri resources eg: /api/v2/host===post + * @return resouce set + */ + @Query("select CONCAT(LOWER(resource.uri),'===', resource.method) " + + "from AuthResourceDO resource where resource.status = 9 order by resource.id") + Optional> getDisableResourcePathData(); + + /** + * Get the available API resources owned by the current role in the form of paging + * @param roleId roleId + * @param request page + * @return api resource list + */ + @Query("select distinct resource from AuthResourceDO resource " + + "left join AuthRoleResourceBindDO bind on bind.resourceId = resource.id " + + "where bind.roleId = :roleId " + + "order by resource.id asc") + Page findRoleOwnResource(@Param("roleId") Long roleId, Pageable request); + + /** + * Get the available API resources owned by the current role in the form of paging + * @param roleId roleId + * @param request page + * @return api resource list + */ + @Query("select distinct resource from AuthResourceDO resource " + + " where resource.id not in " + + "(select distinct bind.resourceId from AuthRoleResourceBindDO bind where bind.roleId = :roleId) " + + "order by resource.id asc ") + Page findRoleNotOwnResource(@Param("roleId") Long roleId, Pageable request); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleDao.java new file mode 100644 index 00000000000..02271cf4121 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleDao.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleDO; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * @author tomsun28 + * @date 16:42 2019-07-27 + */ +public interface AuthRoleDao extends JpaRepository { + + /** + * Query the role owned by the current user + * @param username username + * @return role list + */ + @Query("select ar.name from AuthRoleDO ar, AuthUserDO au, AuthUserRoleBindDO bind " + + "where ar.id = bind.roleId and au.id = bind.userId and au.name = :username") + List findAccountOwnRoles(@Param("username") String username); + + @Query("select ar.id from AuthRoleDO ar where ar.code = :code") + Long queryIdByCode(@Param("code") String code); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleResourceBindDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleResourceBindDao.java new file mode 100644 index 00000000000..7a68eae05c2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthRoleResourceBindDao.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleResourceBindDO; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * @author tomsun28 + * @date 16:43 2019-07-27 + */ +public interface AuthRoleResourceBindDao extends JpaRepository { + + /** + * Query the resources owned by the current role + * @param roleId roleId + * @return resource list + */ + @Query("select rs from AuthResourceDO rs, AuthRoleResourceBindDO bind " + + "where rs.id = bind.resourceId and bind.roleId = :roleId") + List findRoleBindResourceList(@Param("roleId") Long roleId); + + /** + * delete record which roleId and resource equals this + * @param roleId roleID + * @param resourceId resourceId + */ + @Modifying + @Query("delete from AuthRoleResourceBindDO bind " + + "where bind.roleId = :roleId and bind.resourceId = :resourceId") + void deleteRoleResourceBind(@Param("roleId") Long roleId,@Param("resourceId") Long resourceId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserDao.java new file mode 100644 index 00000000000..aa9e142d2f8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserDao.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.AuthUserDO; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +/** + * @author tomsun28 + * @date 16:43 2019-07-27 + */ +public interface AuthUserDao extends JpaRepository { + + /** + * Get user by email + * @param email email + * @return user + */ + @Query("select au from AuthUserDO au where au.email = :email") + Optional findAuthUserByEmail(@Param("email") String email); + + /** + * Query the role owned by the current user + * @param username username + * @return role list + */ + @Query("select ar.code from AuthRoleDO ar, AuthUserDO au, AuthUserRoleBindDO bind " + + "where ar.id = bind.roleId and au.id = bind.userId and au.email = :username") + List findAccountOwnRoles(@Param("username") String username); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserRoleBindDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserRoleBindDao.java new file mode 100644 index 00000000000..804785b90ec --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/AuthUserRoleBindDao.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthUserRoleBindDO; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * @author tomsun28 + * @date 16:44 2019-07-27 + */ +public interface AuthUserRoleBindDao extends JpaRepository { + + /** + * Query the role owned by the current user + * @param userId userId + * @return role list + */ + @Query("select ar from AuthRoleDO ar, AuthUserRoleBindDO bind " + + "where ar.id = bind.roleId and bind.userId = :userId") + List findUserBindRoleList(@Param("userId") Long userId); + + /** + * delete record which roleId and userId equals this + * @param roleId roleID + * @param userId userId + */ + @Query("delete from AuthUserRoleBindDO bind " + + "where bind.roleId = :roleId and bind.userId = :userId") + void deleteRoleResourceBind(@Param("roleId") Long roleId,@Param("userId") Long userId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/CategoryDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/CategoryDao.java new file mode 100644 index 00000000000..d9b11f46242 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/CategoryDao.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.CategoryDO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface CategoryDao extends JpaRepository , Repository { + + List findAllByIsDel(int isDel); + + Page findAllByIsDel(int isDel, Pageable pageable); + + @Modifying(clearAutomatically = true) + @Transactional + @Query(value = "UPDATE category set `is_del` = 1 where id=?", nativeQuery = true) + int deleteByIsDel(int id); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/StarDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/StarDao.java new file mode 100644 index 00000000000..76e813103b4 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/StarDao.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.StarDO; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface StarDao extends JpaRepository , Repository { + + @Modifying(clearAutomatically = true) + @Transactional + @Query(value = "UPDATE star set `is_del` = ? where `user_id` = ? AND template_id=? AND is_del=?", nativeQuery = true) + int cancelByUser(int cancel, int userId,int templateId,int isCancel); + + @Query(value = "select star.template_id from star where `user_id` = ? AND is_del=?", nativeQuery = true) + List queryTemplateIdByUserAndIsDel(int userId, int isDel); + +// @Query(value = "select star.id from star where `user_id` = ? AND is_del=?", nativeQuery = true) + boolean existsStarByTemplateIdAndUserIdAndIsDel(int templateId ,int userId, int isDel); + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/TemplateDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/TemplateDao.java new file mode 100644 index 00000000000..390d0be2f08 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/TemplateDao.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface TemplateDao extends JpaRepository { + + @Query(value = "select id from template where name= ? and `user`= ?",nativeQuery=true) + int queryId(String name, int user); + + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE template set `latest` = ? where `id` = ?",nativeQuery=true) + int updateTemplate(int latest,int id); + + @Query(value = "select COUNT(*) from template where `name` = ? and `user` = ?",nativeQuery=true) + int queryCountByNameAndUser(String name,int user); + + @Query(value = "select COUNT(template.id) from template where `is_del` = ? and off_shelf = ? ",nativeQuery=true) + int queryCountByIsDelAndOffShelf(int isDel, int offShelf); + + @Deprecated + @Query(value = "select * from template where `user` = ? and `is_del` = ?",nativeQuery=true) + List queryByUserId(int user, int isDel); + + @Query(value = "select * from template where `user` = ? and `is_del` = ?", nativeQuery = true) + Page queryPageByUserId(int user, int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where `category_id` = ? and `is_del` = ?",nativeQuery=true) + List queryByCategory(int categoryId, int isDel); + + @Query(value = "select * from template where `category_id` IN ? and `is_del` = ?",nativeQuery=true) + Page queryPageByCategory(List categoryIdList, int isDel, Pageable pageable); + + @Query(value = "select * from template where name like CONCAT('%',?,'%') AND `category_id` IN ? AND `is_del` = ?",nativeQuery=true) + Page queryPageByNameLikeAndCategory(String nameLike, List categoryIdList, int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del=? AND name like CONCAT('%',?,'%') ",nativeQuery = true) + List queryByNameLike(int isDel, String name); + + @Query(value = "select * from template where is_del=? AND name like CONCAT('%',?,'%') ",nativeQuery = true) + Page queryPageByNameLike(int isDel, String name, Pageable pageable); + + @Query(value = "select * from template where `is_del` = ?",nativeQuery=true) + List queryAllByIsDel(int isDel); + + @Query(value = "select * from template where `is_del` = ?",nativeQuery=true) + Page queryPageByIsDel(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by create_time desc ",nativeQuery = true) + List queryAllByIsDelOrderByCreateTimeDesc(int isDel); + + @Query(value = "select * from template where is_del = ? order by create_time desc ",nativeQuery = true) + Page queryPageByIsDelOrderByCreateTimeDesc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by create_time",nativeQuery = true) + List queryAllByIsDelOrderByCreateTimeAsc(int isDel); + + @Query(value = "select * from template where is_del = ? order by create_time",nativeQuery = true) + Page queryPageByIsDelOrderByCreateTimeAsc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by update_time desc ",nativeQuery = true) + List getByIsDelOrderByUpdateTimeDesc(int isDel); + + @Query(value = "select * from template where is_del = ? order by update_time desc ",nativeQuery = true) + Page queryPageByIsDelOrderByUpdateTimeDesc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by update_time",nativeQuery = true) + List getByIsDelOrderByUpdateTimeAsc(int isDel); + + @Query(value = "select * from template where is_del = ? order by update_time",nativeQuery = true) + Page queryPageByIsDelOrderByUpdateTimeAsc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by star desc ",nativeQuery = true) + List getByIsDelOrderByStarDesc(int isDel); + + @Query(value = "select * from template where is_del = ? order by star desc ",nativeQuery = true) + Page queryPageByIsDelOrderByStarDesc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by star",nativeQuery = true) + List getByIsDelOrderByStarAsc(int isDel); + + @Query(value = "select * from template where is_del = ? order by star",nativeQuery = true) + Page queryPageByIsDelOrderByStarAsc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by download desc ",nativeQuery = true) + List getByIsDelOrderByDownloadDesc(int isDel); + + @Query(value = "select * from template where is_del = ? order by download desc ",nativeQuery = true) + Page queryPageByIsDelOrderByDownloadDesc(int isDel, Pageable pageable); + + @Deprecated + @Query(value = "select * from template where is_del = ? order by download",nativeQuery = true) + List getByIsDelOrderByDownloadAsc(int isDel); + + @Query(value = "select * from template where is_del = ? order by download",nativeQuery = true) + Page queryPageByIsDelOrderByDownloadAsc(int isDel, Pageable pageable); + + @Transactional + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE template set `download` = `download` + ? where `id` = ?",nativeQuery=true) + int downloadUpdate(int num, int id); + + TemplateDO findTemplateById(int id); + + @Transactional + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE template set star = star - ? where `id` = ? AND is_del=0 AND off_shelf=0",nativeQuery=true) + int cancelStarTemplate(int num, int templateId); + + @Transactional + @Query(value = "select template.* from template left join star on template.id = star.template_id where star.user_id = ? AND star.is_del=? AND template.is_del=? AND template.off_shelf=?", nativeQuery = true) + Page queryPageByUserStar(int userId, int isCancel, int isDel, int offShelf, Pageable pageable); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/VersionDao.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/VersionDao.java new file mode 100644 index 00000000000..cc090f3dac2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dao/VersionDao.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DAO; + +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface VersionDao extends JpaRepository , Repository { + + /** + * Query the inserted version ID based on the template ID and version number + * @return Returns the version id of the query + */ + @Query(value = "select id from version where `template_id` = ? and `version` = ?", nativeQuery = true) + int queryId(int templateId, String version); + + /** + * Check whether there is the same version data according to the template id and version number, that is, query the number + * @return Returns the number of versions queried + */ + @Query(value = "SELECT COUNT(*) from version where `template_id` = ? and `version` = ?", nativeQuery = true) + int queryCountByTemplateAndVersion(int templateId, String version); + + @Deprecated + @Query(value = "select * from version where `template_id` = ? and `is_del` = 0", nativeQuery = true) + List queryVersionByTemplateId(int templateId); + + @Query(value = "select * from version where `template_id` = ? and `is_del` = ?", nativeQuery = true) + Page queryPageByTemplateId(int templateId, int isDel, Pageable pageable); + + @Transactional + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE version set `download` = `download` + ? where `id` = ?",nativeQuery=true) + int downloadUpdate(int num, int id); + + @Deprecated + @Transactional + @Query(value = "select version.* from version left join star on version.id = star.version_id where star.user_id = ? AND star.is_del=? AND version.is_del=? AND version.off_shelf=?", nativeQuery = true) + List findAllByUserStar(int userId, int isCancel, int isDel, int offShelf); + + + @Transactional + @Modifying(clearAutomatically = true) + @Query(value = "UPDATE version set star = version.star - ? where `id` = ? AND is_del=0 AND off_shelf=0",nativeQuery=true) + int cancelStarVersion(int num, int versionId); + + @Transactional + @Query(value = "select version.* from version join template on version.id = template.latest where template.id = ?", nativeQuery = true) + VersionDO queryLatestByTemplate(int templateId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/LoginDto.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/LoginDto.java new file mode 100644 index 00000000000..6909ab16f09 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/LoginDto.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY; + +/** + * Login registered account information transfer body email + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "Account information transfer body") +public class LoginDto { + + /** + * type + * 1. Account (email) username password login 2. github login + */ + @Schema(description = "type", example = "1", accessMode = READ_ONLY) + @Max(value = 4, message = "1. Account (email) password login 2. github login 3. WeChat login") + private Byte type; + + /** + * User ID + */ + @Schema(description = "user identification", example = "1", accessMode = READ_ONLY) + @NotBlank(message = "Identifier can not null") + private String identifier; + + /** + * key + */ + @Schema(description = "Secret key", example = "1", accessMode = READ_ONLY) + @NotBlank(message = "Credential can not null") + @Size(max = 512, message = "credential max length 512") + private String credential; + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/Message.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/Message.java new file mode 100644 index 00000000000..6586eac7c6d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/Message.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.ToString; +import org.apache.hertzbeat.templatehub.constants.CommonConstants; + +/** + * Unified message structure definition for front and back ends + *

+ * { + * data:{....}, + * msg: message, + * code: 3432 + * } + */ + +@Data +@ToString +@Builder +@AllArgsConstructor +public class Message { + + /** + * response code, not http code + */ + @Schema(title = "Response Code") + private byte code = CommonConstants.SUCCESS_CODE; + + /** + * exception message when error happen or success message + */ + @Schema(title = "Other Message") + private String msg; + + /** + * message body data + */ + @Schema(description = "Response Data") + private T data; + + public static Message success() { + return new Message<>(); + } + + public static Message success(String msg) { + return new Message<>(msg); + } + + public static Message fail(byte code, String msg) { + return new Message<>(code, msg); + } + + public static Message success(T data) { + return new Message<>(data); + } + + public static Message successWithData(T data) { + return new Message<>(data); + } + + private Message() { + } + + private Message(String msg) { + this.msg = msg; + } + + private Message(byte code, String msg) { + this.code = code; + this.msg = msg; + } + + private Message(T data) { + this.data = data; + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/RefreshTokenResponse.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/RefreshTokenResponse.java new file mode 100644 index 00000000000..fcbeb882ff5 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/RefreshTokenResponse.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Refresh Token Response + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Schema(description = "flash token response") +public class RefreshTokenResponse { + @Schema(title = "Access Token") + private String token; + + @Schema(title = "Refresh Token") + private String refreshToken; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/SignUpDto.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/SignUpDto.java new file mode 100644 index 00000000000..780d9602bf3 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/SignUpDto.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY; + +/** + * Login registered account information transfer body email + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "sign up body") +public class SignUpDto { + + @Schema(description = "name", example = "user", accessMode = READ_ONLY) + @NotBlank(message = "Name can not null") + @Size(max = 10, message = "name max length 10") + private String name; + + @Schema(description = "user email", example = "xxx@xxx.com", accessMode = READ_ONLY) + @NotBlank(message = "email can not null") + private String email; + + @Schema(description = "password", example = "123456", accessMode = READ_ONLY) + @NotBlank(message = "password can not null") + @Size(min = 6,max = 16, message = "password max length 16,min 6") + private String password; + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TemplateDto.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TemplateDto.java new file mode 100644 index 00000000000..d63128dda45 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TemplateDto.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class TemplateDto { + + private int id=0; + private String name=""; + private String description=""; + private String descriptionVersion=""; + private int latest=0; + private String currentVersion=""; + private String user=""; + private int userId=0; + private String category=""; + private int categoryId=0; + private int download=0; + private int star=0; + private String create_time=""; + private String update_time=""; + private int off_shelf=0; + private int is_del=0; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TokenDto.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TokenDto.java new file mode 100644 index 00000000000..47686db0318 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/dto/TokenDto.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Refresh token dto + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "Request refresh token transfer body") +public class TokenDto { + + @Schema(description = "token") + @NotBlank(message = "token can not null") + private String token; + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Category.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Category.java new file mode 100644 index 00000000000..9da3ab446f0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Category.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "category") +public class Category implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "Category Name") + private String name; + + @Column(nullable = false) + private String description; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false, name = "update_time") + private String updateTime; + + @Column(nullable = false,name = "is_del") + @Schema(description = "Delete Mark") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Star.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Star.java new file mode 100644 index 00000000000..b4fd1f99cae --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Star.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Table(name = "star") +@Entity +public class Star implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "user_id",nullable = false) + private Integer userId; + + @Column(name = "template_id",nullable = false) + private Integer templateId; + + @Column(name = "version_id",nullable = false) + private Integer versionId; + + @Column(name = "create_time",nullable = false) + private String createTime; + + @Column(name = "is_del",nullable = false) + @Schema(description = "Cancel flag, 0 means normal, 1 means cancel") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Tag.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Tag.java new file mode 100644 index 00000000000..60a41f96657 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Tag.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "tag") +public class Tag implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Schema(description = "Tag name, no duplication allowed, modification allowed") + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String description; + + @Column(name = "create_time",nullable = false) + private String createTime; + + @Column(name = "is_del",nullable = false) + private Integer isDel; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Template.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Template.java new file mode 100644 index 00000000000..a572f1dfb5e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Template.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name="template") +public class Template implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id=1; + + @Column(nullable = false) + @Schema(description = "Template name, cannot be modified, but can be repeated") + private String name; + + @Column(nullable = false) + private String description; + + @Column(nullable = false) + @Schema(description = "Latest version id") + private Integer latest; + + @Column(nullable = false) + @Schema(description = "user id") + private Integer user; + + @Column(nullable = false) + @Schema(description = "Template category id") + private Integer category; + + @Column(nullable = false) + @Schema(description = "Template-tag table id") + private Integer tag; + + @Column(nullable = false) + @Schema(description = "Downloads") + private Integer download; + + @Column(nullable = false) + private Integer star; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false, name = "update_time") + private String updateTime; + + @Column(nullable = false,name="off_shelf") + @Schema(description = "Delisting mark, 0 means normal, 1 means delisting") + private Integer offShelf; + + @Column(nullable = false,name = "is_del") + @Schema(description = "Delete mark, 0 means normal, 1 means delete") + private Integer isDel; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/TemplateTag.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/TemplateTag.java new file mode 100644 index 00000000000..24477198e7f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/TemplateTag.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "template_tag") +public class TemplateTag implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "template id") + private Integer template; + + @Column(nullable = false) + @Schema(description = "tag id") + private Integer tag; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/User.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/User.java new file mode 100644 index 00000000000..b517b4d0a14 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/User.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "user") +public class User implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "Username, can be repeated, can be modified") + private String name; + + @Column(nullable = false) + @Schema(description = "Email, can be modified, used for user login") + private String email; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false,name = "log_off_time") + @Schema(description = "Logout time, if not logged out it is 0, if logged out it is time") + private String logOffTime; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Version.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Version.java new file mode 100644 index 00000000000..3f983a764d2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/model/entity/Version.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.model.entity; + +import java.io.Serializable; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ToString +@Entity +@Table(name = "version") +public class Version implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(nullable = false) + @Schema(description = "template id") + private Integer template; + + @Column(nullable = false) + @Schema(description = "Version name, modification is not allowed") + private String version; + + @Column(nullable = false) + @Schema(description = "Version description") + private String description; + + @Column(nullable = false) + private Integer download; + + @Column(nullable = false) + private Integer star; + + @Column(nullable = false,name = "create_time") + private String createTime; + + @Column(nullable = false,name = "off_shelf") + private Integer offShelf; + + @Column(nullable = false,name = "is_del") + private Integer isDel; + + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/AccountService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/AccountService.java new file mode 100644 index 00000000000..e189064f41d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/AccountService.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import com.usthe.sureness.provider.SurenessAccount; +import org.apache.hertzbeat.templatehub.model.DTO.LoginDto; +import org.apache.hertzbeat.templatehub.model.DTO.RefreshTokenResponse; +import org.apache.hertzbeat.templatehub.model.DTO.SignUpDto; + +import javax.naming.AuthenticationException; +import java.util.List; +import java.util.Map; + +/** + * Account service + */ +public interface AccountService { + /** + * Verify account validity, username and password + * @param account account info + * @return success-true failed-false + */ + boolean authenticateAccount(LoginDto account); + + /** + * Get all roles owned by this username account, combine them into string list + * @param username account username + * @return role-string eg role1,role3,role2 + */ + List loadAccountRoles(String username); + + /** + * register account + * @param account account info + * @return success-true failed-false + */ + boolean registerAccount(SignUpDto account); + + /** + * Determine whether the account already exists + * @param account account info + * @return exist-true no-false + */ + boolean isAccountExist(LoginDto account); + + /** + * Account password login to obtain associated user information + * @param loginDto loginDto + * @return token info + * @throws AuthenticationException when authentication is failed + */ + Map authGetToken(LoginDto loginDto) throws AuthenticationException; + + /** + * Load the account information by username + * @param username account username + * @return account + */ + SurenessAccount loadAccount(String username); + + /** + * authority User Role by username and roleId + * @param appId account username + * @param roleId roleId + * @return success-true failed-false + */ + boolean authorityUserRole(String appId, Long roleId); + + /** + * delete authority User Role by username and roleId + * @param appId account username + * @param roleId roleId + * @return success-true failed-false + */ + boolean deleteAuthorityUserRole(String appId, Long roleId); + + /** + * Use refresh TOKEN to re-acquire TOKEN + * @param refreshToken refreshToken + * @return token and refresh token + * @throws Exception failed to refresh + */ + RefreshTokenResponse refreshToken(String refreshToken) throws Exception; +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/CategoryService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/CategoryService.java new file mode 100644 index 00000000000..fa3c8426c89 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/CategoryService.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.CategoryDO; +import org.springframework.data.domain.Page; + +import java.util.List; + +public interface CategoryService { + + boolean addCategory(String categoryName,String categoryDescription,String nowTime); + + boolean modifyCategory(int id, String categoryName,String categoryDescription,String nowTime); + + boolean deleteCategory(int id); + + List getAllCategoryByIsDel(int isDel); + + Page getPageByIsDel(int isDel, int page, int size); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/FileStorageService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/FileStorageService.java new file mode 100644 index 00000000000..5df5a0cd491 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/FileStorageService.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.springframework.core.io.Resource; +import org.springframework.web.multipart.MultipartFile; + +public interface FileStorageService { + + void uploadFile(MultipartFile file, String path, String fileName); + + void deleteFile(String path, String fileName); + + Resource downloadFile(String path, String fileName); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/ResourceService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/ResourceService.java new file mode 100644 index 00000000000..7587d639a17 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/ResourceService.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * @author tomsun28 + * @date 00:13 2019-08-01 + */ +public interface ResourceService { + + /** + * add uri resource + * @param authResource resource + * @return success-true failed-false + */ + boolean addResource(AuthResourceDO authResource); + + /** + * Determine whether the resource already exists + * @param authResource resource + * @return existed-true no-false + */ + boolean isResourceExist(AuthResourceDO authResource); + + /** + * update uri resource + * @param authResource resource + * @return success-true failed-false + */ + boolean updateResource(AuthResourceDO authResource); + + /** + * delete uri resource + * @param resourceId resource ID + * @return success-true no existed-false + */ + boolean deleteResource(Long resourceId); + + /** + * get all resources + * @return resource list + */ + Optional> getAllResource(); + + /** + * get resource by page + * @param currentPage current page + * @param pageSize page size + * @return Page of resource + */ + Page getPageResource(Integer currentPage, Integer pageSize); + + /** + * get enabled resource-path-role eg: /api/v2/host===post===[role2,role3,role4] + * @return resource-path-role + */ + Set getAllEnableResourcePath(); + + /** + * get disable resource-path-role eg: /api/v2/host===post===[role2,role3,role4] + * @return resource-path-role + */ + Set getAllDisableResourcePath(); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/RoleService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/RoleService.java new file mode 100644 index 00000000000..ba56707ff12 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/RoleService.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleDO; +import org.springframework.data.domain.Page; + +import java.util.List; +import java.util.Optional; + +public interface RoleService { + + Long getRoleIdByCode(String code); + + /** + * Determine whether the role already exists + * @param authRole role + * @return existed-true no-false + */ + boolean isRoleExist(AuthRoleDO authRole); + + /** + * add role + * @param authRole role + * @return add success-true failed-false + */ + boolean addRole(AuthRoleDO authRole); + + /** + * update role + * @param authRole role + * @return success-true failed-false + */ + boolean updateRole(AuthRoleDO authRole); + + /** + * delete role + * @param roleId role ID + * @return success-true failed-false + */ + boolean deleteRole(Long roleId); + + /** + * get all role list + * @return role list + */ + Optional> getAllRole(); + + /** + * get roles page + * @param currentPage current page + * @param pageSize page size + * @return Page of roles + */ + Page getPageRole(Integer currentPage, Integer pageSize); + + /** + * get pageable resources which this role owned + * @param roleId role ID + * @param currentPage current page + * @param pageSize page size + * @return Page of resources + */ + Page getPageResourceOwnRole(Long roleId, Integer currentPage, Integer pageSize); + + /** + * get pageable resources which this role not owned + * @param roleId role ID + * @param currentPage current page + * @param pageSize page size + * @return Page of resources + */ + Page getPageResourceNotOwnRole(Long roleId, Integer currentPage, Integer pageSize); + + /** + * authority this resource to this role + * @param roleId role ID + * @param resourceId resource ID + */ + void authorityRoleResource(Long roleId, Long resourceId); + + /** + * unAuthority this resource in this role + * @param roleId role ID + * @param resourceId resource ID + */ + void deleteAuthorityRoleResource(Long roleId, Long resourceId); + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/StarService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/StarService.java new file mode 100644 index 00000000000..438e7cf8c7e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/StarService.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.springframework.data.domain.Page; + +import java.util.List; + +public interface StarService { + int starTemplate(int userId, int templateId, String nowTime); + + boolean assertTemplateIdIsStarByUser(int userId, int templateId); + + List getTemplateByUserStar(int userId, int isDel); + + Page getPageByUserStar(int userId, int isCancel, int isDel, int offShelf, int page, int size); + + Boolean cancelStarByUser(int userId, int templateId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TagService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TagService.java new file mode 100644 index 00000000000..19f91f273de --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TagService.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +public interface TagService{ + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateService.java new file mode 100644 index 00000000000..ac806ed10d1 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateService.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface TemplateService { + + int getCountByIsDelAndOffShelf(int isDel, int offShelf); + + boolean upload(TemplateDto templateDto, MultipartFile file); + + Page getPageByUserId(int userId, int page, int size); + + Page getPageByCategory(List categoryIdList, int isDel, int orderOption, int page, int size); + + Page getPageByOption(String nameLike, List categoryIdList, int isDel, int orderOption, int page, int size); + + Page getPageByIsDelOrderByCreateTimeDesc(int isDel, int page, int size); + + Page getPageByIsDelOrderByCreateTimeAsc(int isDel, int page, int size); + + Page getPageByIsDelOrderByUpdateTimeDesc(int isDel, int page, int size); + + Page getPageByIsDelOrderByUpdateTimeAsc(int isDel, int page, int size); + + Page getPageByIsDelOrderByStarDesc(int isDel, int page, int size); + + Page getPageByIsDelOrderByStarAsc(int isDel, int page, int size); + + Page getPageByIsDelOrderByDownloadDesc(int isDel, int page, int size); + + Page getPageByIsDelOrderByDownloadAsc(int isDel, int page, int size); + + Page getPageByNameLike(String name, int isDel, int orderOption, int page, int size); + + Page getTemplatesByPage(int isDel, int page, int size); + + Resource downloadTemplate(int ownerId, int templateId, String version, int versionId); + + boolean deleteTemplate(int ownerId, int templateId, String version); + + TemplateDO getTemplate(int templateId); + + boolean starTemplate(int templateId); + + boolean cancelStarTemplate(int templateId); + + List getAllTemplates(); + +// @Deprecated +// List getTemplatesByCategory(int categoryId); +// +// @Deprecated +// List getByIsDelOrderByCreateTimeDesc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByCreateTimeAsc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByUpdateTimeDesc(int isDel); +// +// @Deprecated +// List getPageByIsDelOrderByUpdateTimeAsc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByStarDesc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByStarAsc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByDownloadDesc(int isDel); +// +// @Deprecated +// List getByIsDelOrderByDownloadAsc(int isDel); +// +// @Deprecated +// List getTemplatesByNameLike(String name); +// +// @Deprecated +// ResponseEntity>> getAllTemplatesByUserId(int userId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateTagService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateTagService.java new file mode 100644 index 00000000000..58fe9695c4e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/TemplateTagService.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +public interface TemplateTagService { + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/UserService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/UserService.java new file mode 100644 index 00000000000..ff986c146a0 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/UserService.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +public interface UserService { + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/VersionService.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/VersionService.java new file mode 100644 index 00000000000..68555ce70aa --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/VersionService.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service; + +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.springframework.data.domain.Page; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface VersionService { + + boolean insertVersion(VersionDO versionDO, TemplateDO templateDO); + + List getVersions(int templateId); + + Page getVersionPageByTemplate(int templateId, int isDel, int page, int size); + + boolean upload(TemplateDto templateDto, MultipartFile file); + + VersionDO getVersion(int versionId); + + VersionDO getLatestVersion(int templateId); + +// boolean startVersion(int versionId); + +// int cancelStarVersion(int versionId); +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/AccountServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/AccountServiceImpl.java new file mode 100644 index 00000000000..232ee3823a8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/AccountServiceImpl.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import com.usthe.sureness.provider.DefaultAccount; +import com.usthe.sureness.provider.SurenessAccount; +import com.usthe.sureness.util.JsonWebTokenUtil; +import com.usthe.sureness.util.Md5Util; +import com.usthe.sureness.util.SurenessCommonUtil; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.hertzbeat.templatehub.model.DAO.AuthUserDao; +import org.apache.hertzbeat.templatehub.model.DAO.AuthUserRoleBindDao; +import org.apache.hertzbeat.templatehub.model.DTO.LoginDto; +import org.apache.hertzbeat.templatehub.model.DTO.RefreshTokenResponse; +import org.apache.hertzbeat.templatehub.model.DO.AuthUserDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthUserRoleBindDO; +import org.apache.hertzbeat.templatehub.model.DTO.SignUpDto; +import org.apache.hertzbeat.templatehub.service.AccountService; +import org.apache.hertzbeat.templatehub.util.JsonUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +import javax.naming.AuthenticationException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * Implementation of Account service + */ +@Service +@Order(value = Ordered.HIGHEST_PRECEDENCE) +@Slf4j +public class AccountServiceImpl implements AccountService { + /** + * Token validity time in seconds + */ + private static final long PERIOD_TIME = 3600L; + + @Autowired + private AuthUserDao authUserDao; + + @Autowired + private AuthUserRoleBindDao userRoleBindDao; + + @Override + public Map authGetToken(LoginDto loginDto) throws AuthenticationException { + SurenessAccount account = loadAccount(loginDto.getIdentifier()); + if (account == null || StringUtils.isBlank(account.getPassword())) { + throw new AuthenticationException("Incorrect Account or Password"); + } else { + String password = loginDto.getCredential(); + if (StringUtils.isNotBlank(account.getSalt())) { + password = Md5Util.md5(password + account.getSalt()); + } + if (!account.getPassword().equals(password)) { + throw new AuthenticationException("Incorrect Account or Password"); + } + if (account.isDisabledAccount() || account.isExcessiveAttempts()) { + throw new AuthenticationException("Expired or Illegal Account"); + } + } + // Get the roles the user has - rbac + List roles = account.getOwnRoles(); + // Issue TOKEN + String issueToken = JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME, roles); + Map customClaimMap = new HashMap<>(1); + customClaimMap.put("refresh", true); + String issueRefresh = JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME << 5, customClaimMap); + Map resp = new HashMap<>(2); + resp.put("token", issueToken); + resp.put("refreshToken", issueRefresh); + resp.put("role", JsonUtil.toJson(roles)); + + Optional authUserByEmail = this.authUserDao.findAuthUserByEmail(loginDto.getIdentifier()); + resp.put("id", String.valueOf(authUserByEmail.map(AuthUserDO::getId).orElse(null))); + + return resp; + } + + @Override + public boolean authenticateAccount(LoginDto account) { + Optional authUserOptional = authUserDao.findAuthUserByEmail(account.getIdentifier()); + if (authUserOptional.isEmpty()) { + return false; + } + AuthUserDO authUser = authUserOptional.get(); + String password = account.getCredential(); + if (password == null) { + return false; + } + if (Objects.nonNull(authUser.getSalt())) { + // md5 with salt + password = Md5Util.md5(password + authUser.getSalt()); + + } + return authUser.getPassword().equals(password); + } + + @Override + public List loadAccountRoles(String username) { + return authUserDao.findAccountOwnRoles(username); + } + + @Override + public boolean registerAccount(SignUpDto account) { + if (isAccountExist(new LoginDto((byte) 1, account.getEmail(), account.getPassword()))) { + return false; + } + String salt = SurenessCommonUtil.getRandomString(6); + String password = Md5Util.md5(account.getPassword() + salt); + AuthUserDO authUser = AuthUserDO.builder().name(account.getName()) + .password(password).salt(salt).status(1).build(); + + authUser.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + authUser.setUpdateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + authUser.setLogOffTime("0"); + authUser.setEmail(account.getEmail()); + + authUserDao.save(authUser); + return true; + } + + @Override + public boolean isAccountExist(LoginDto account) { + Optional authUserOptional = authUserDao.findAuthUserByEmail(account.getIdentifier()); + return authUserOptional.isPresent(); + } + + @Override + public SurenessAccount loadAccount(String username) { + Optional authUserOptional = authUserDao.findAuthUserByEmail(username); + if (authUserOptional.isPresent()) { + AuthUserDO authUser = authUserOptional.get(); + DefaultAccount.Builder accountBuilder = DefaultAccount.builder(username) + .setPassword(authUser.getPassword()) + .setSalt(authUser.getSalt()) + .setDisabledAccount(1 != authUser.getStatus()) + .setExcessiveAttempts(2 == authUser.getStatus()); + List roles = loadAccountRoles(username); + if (roles != null) { + accountBuilder.setOwnRoles(roles); + } + return accountBuilder.build(); + } else { + return null; + } + } + + @Override + public RefreshTokenResponse refreshToken(String refreshToken) throws Exception { + Claims claims = JsonWebTokenUtil.parseJwt(refreshToken); + String userId = String.valueOf(claims.getSubject()); + boolean isRefresh = claims.get("refresh", Boolean.class); + if (StringUtils.isBlank(userId) || !isRefresh) { + throw new AuthenticationException("Illegal Refresh Token"); + } + SurenessAccount account = loadAccount(userId); + if (account == null) { + throw new AuthenticationException("Not Exists This Token Mapping Account"); + } + List roles = account.getOwnRoles(); + String issueToken = issueToken(userId, roles, PERIOD_TIME); + String issueRefresh = issueToken(userId, roles, PERIOD_TIME << 5); + return new RefreshTokenResponse(issueToken, issueRefresh); + } + + private String issueToken(String userId, List roles, long expirationMillis) { + Map customClaimMap = new HashMap<>(1); + customClaimMap.put("refresh", true); + return JsonWebTokenUtil.issueJwt(userId, expirationMillis, roles, customClaimMap); + } + + @Override + public boolean authorityUserRole(String appId, Long roleId) { + Optional optional = authUserDao.findAuthUserByEmail(appId); + if (optional.isEmpty()) { + return false; + } + Long userId = optional.get().getId(); + AuthUserRoleBindDO userRoleBindDO = AuthUserRoleBindDO.builder().userId(userId).roleId(roleId).build(); + + userRoleBindDao.save(userRoleBindDO); + return true; + } + + @Override + public boolean deleteAuthorityUserRole(String appId, Long roleId) { + Optional optional = authUserDao.findAuthUserByEmail(appId); + if (optional.isEmpty()) { + return false; + } + Long userId = optional.get().getId(); + userRoleBindDao.deleteRoleResourceBind(roleId, userId); + return true; + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/CategoryServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/CategoryServiceImpl.java new file mode 100644 index 00000000000..947b7fd6715 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/CategoryServiceImpl.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DAO.CategoryDao; +import org.apache.hertzbeat.templatehub.model.DAO.TemplateDao; +import org.apache.hertzbeat.templatehub.model.DO.CategoryDO; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.service.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Slf4j +@Service +public class CategoryServiceImpl implements CategoryService { + + @Autowired + CategoryDao categoryDao; + + @Autowired + TemplateDao templateDao; + + @Override + public boolean addCategory(String categoryName, String categoryDescription, String nowTime) { + + CategoryDO save = categoryDao.save(new CategoryDO(0, categoryName, categoryDescription, nowTime, nowTime, 0)); + + return save.getId() > 0; + } + + @Override + public boolean modifyCategory(int id, String categoryName, String categoryDescription, String nowTime) { + + Optional byId = categoryDao.findById(id); + + if(byId.isEmpty()){ + return false; + } + CategoryDO categoryDO = byId.get(); + categoryDO.setName(categoryName); + categoryDO.setDescription(categoryDescription); + categoryDO.setUpdateTime(nowTime); + + categoryDao.save(categoryDO); + + return true; + } + + @Override + public boolean deleteCategory(int id) { + + List ids = new ArrayList<>(); + ids.add(id); + Page templates = templateDao.queryPageByCategory(ids, 0, PageRequest.of(0,1)); + + if(templates.getTotalElements()!=0){ + return false; + } + int i = categoryDao.deleteByIsDel(id); + return i > 0; + } + + @Override + public List getAllCategoryByIsDel(int isDel) { + return categoryDao.findAllByIsDel(isDel); + } + + @Override + public Page getPageByIsDel(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return categoryDao.findAllByIsDel(isDel,pageable); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/DataConflictException.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/DataConflictException.java new file mode 100644 index 00000000000..7c429656aa6 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/DataConflictException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + + +/** + * data conflict exception + * @author tomsun28 + * @date 22:55 2020-04-27 + */ +public class DataConflictException extends RuntimeException { + + public DataConflictException(String msg) { + super(msg); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/LocalFileStorageServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/LocalFileStorageServiceImpl.java new file mode 100644 index 00000000000..82f0f076ecf --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/LocalFileStorageServiceImpl.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.service.FileStorageService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +@Service +public class LocalFileStorageServiceImpl implements FileStorageService { + + @Value("${local.storage.path}") + private String storagePath; + + @Override + public void uploadFile(MultipartFile file, String path, String fileName) { + try { + // Ensure the directory exists + File directory = new File(storagePath+"/"+path); + if (!directory.exists()) { + boolean mkdir = directory.mkdirs(); + if(!mkdir){ + throw new RuntimeException("Unable to create directory"); + } + } + + // Define the file path + File localFile = new File(directory,fileName); + try (FileOutputStream outputStream = new FileOutputStream(localFile)) { + outputStream.write(file.getBytes()); + } + + // Return the file URL (local file path in this case) +// return localFile.toURI().toString(); + } catch (IOException e) { + throw new RuntimeException("Error uploading file to local storage", e); + } + } + + @Override + public void deleteFile(String path, String fileName) { + File file = new File(storagePath + "/" + path + "/" + fileName); + if (file.exists() && !file.delete()) { + throw new RuntimeException("Error deleting file from local storage"); + } + } + + @Override + public Resource downloadFile(String path, String fileName) { + File file = new File(storagePath + "/" + path + "/" + fileName); + if (file.exists()) { + return new FileSystemResource(file); + } else { + throw new RuntimeException("File not found"); + } + } +} + diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/MinIOFileStorageServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/MinIOFileStorageServiceImpl.java new file mode 100644 index 00000000000..3937b68c414 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/MinIOFileStorageServiceImpl.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import io.minio.*; +import io.minio.errors.MinioException; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.service.FileStorageService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.InputStreamResource; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +@Slf4j +@Service +public class MinIOFileStorageServiceImpl implements FileStorageService { + + @Value("${minio.endpoint}") + private String minioEndpoint; + + @Value("${minio.accessKey}") + private String accessKey; + + @Value("${minio.secretKey}") + private String secretKey; + + @Value("${minio.bucketName}") + private String bucketName; + + private final MinioClient minioClient; + + public MinIOFileStorageServiceImpl( + @Value("${minio.endpoint}") String minioEndpoint, + @Value("${minio.accessKey}") String accessKey, + @Value("${minio.secretKey}") String secretKey) { + this.minioClient = MinioClient.builder() + .endpoint(minioEndpoint) + .credentials(accessKey, secretKey) + .build(); + } + + /** + * uploadFile + * + * @param file Upload file information + * @param path Storage path in MinIO + */ + @Override + public void uploadFile(MultipartFile file, String path, String fileName) { + try { + + if(minioEndpoint==null||accessKey==null||secretKey==null){ + throw new IllegalArgumentException("Minio configuration error"); + } + + // Check if the bucket exists, if not, create it + boolean isExist = minioClient.bucketExists( + BucketExistsArgs.builder() + .bucket(bucketName) + .build()); + if (!isExist) { + minioClient.makeBucket( + MakeBucketArgs.builder() + .bucket(bucketName) + .build()); + } + + // Upload files to bucket + String contentType = file.getContentType(); + InputStream inputStream = file.getInputStream(); + long size = file.getSize(); + + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .stream(inputStream, size, -1) + .contentType(contentType) + .object(path+"/"+fileName) + .bucket(bucketName) + .build()); + } catch (MinioException | NoSuchAlgorithmException | InvalidKeyException | IOException e) { + throw new RuntimeException("File upload error:", e); + } +// return path+"/"+fileName; + } + + @Override + public void deleteFile(String path, String fileName) { + try { + minioClient.removeObject(RemoveObjectArgs.builder() + .bucket(bucketName) + .object(path + "/" + fileName) + .build()); + } catch (Exception e) { + throw new RuntimeException("Error deleting file from MinIO", e); + } + } + + @Override + public Resource downloadFile(String path, String fileName) { + + Boolean isExist = checkFileIsExist(bucketName, path + "/" + fileName); + + if(!isExist){ + return null; + } + + try { + InputStream inputStream = minioClient.getObject(GetObjectArgs.builder() + .bucket(bucketName) + .object(path + "/" + fileName) + .build()); + return new InputStreamResource(inputStream); + } catch (MinioException | IOException e) { + throw new RuntimeException("Error downloading file from MinIO", e); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + throw new RuntimeException(e); + } + } + + public Boolean checkFileIsExist(String bucketName, String objectName) { + try { + minioClient.statObject( + StatObjectArgs.builder().bucket(bucketName).object(objectName).build() + ); + } catch (Exception e) { + return false; + } + return true; + } + + +// /** +// * Retrieve file external links +// * @param path File Path +// * @param expires Expiration time unit: days +// * @return url +// */ +// @Override +// public String getDownloadUrl(String path, Integer expires) throws Exception { +// +// MinioClient minioClient =MinioClient.builder() +// .endpoint(minioEndpoint) +// .credentials(accessKey,secretKey) +// .build(); +// +// GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() +// .method(Method.GET) +// .expiry(expires, TimeUnit.DAYS) +// .object(path) +// .bucket(bucketName) +// .build(); +// return minioClient.getPresignedObjectUrl(args); +// } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/ResourceServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/ResourceServiceImpl.java new file mode 100644 index 00000000000..768138d1584 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/ResourceServiceImpl.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.model.DAO.AuthResourceDao; +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.service.ResourceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * @author tomsun28 + * @date 13:09 2019-08-04 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class ResourceServiceImpl implements ResourceService { + + @Autowired + private AuthResourceDao authResourceDao; + + @Override + public boolean addResource(AuthResourceDO authResource) { + if (isResourceExist(authResource)) { + return false; + } else { + authResourceDao.saveAndFlush(authResource); + return true; + } + } + + @Override + public boolean isResourceExist(AuthResourceDO authResource) { + AuthResourceDO resource = AuthResourceDO.builder() + .uri(authResource.getUri()) + .method(authResource.getMethod()) + .build(); + Example example = Example.of(resource); + return authResourceDao.exists(example); + } + + @Override + public boolean updateResource(AuthResourceDO authResource) { + if (authResourceDao.existsById(authResource.getId())) { + authResourceDao.saveAndFlush(authResource); + return true; + } else { + return false; + } + } + + @Override + public boolean deleteResource(Long resourceId) { + if (authResourceDao.existsById(resourceId)) { + authResourceDao.deleteById(resourceId); + return true; + } else { + return false; + } + } + + @Override + public Optional> getAllResource() { + List resourceList = authResourceDao.findAll(); + return Optional.of(resourceList); + } + + @Override + public Page getPageResource(Integer currentPage, Integer pageSize) { + PageRequest pageRequest = PageRequest.of(currentPage, pageSize); + return authResourceDao.findAll(pageRequest); + } + + @Override + public Set getAllEnableResourcePath() { + Optional> optional = authResourceDao.getEnableResourcePathRoleData(); + return optional.>map(HashSet::new).orElseGet(() -> new HashSet<>(0)); + } + + @Override + public Set getAllDisableResourcePath() { + Optional> optional = authResourceDao.getDisableResourcePathData(); + return optional.>map(HashSet::new).orElseGet(() -> new HashSet<>(0)); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/RoleServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/RoleServiceImpl.java new file mode 100644 index 00000000000..3cfed6c28cd --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/RoleServiceImpl.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import com.usthe.sureness.matcher.TreePathRoleMatcher; +import org.apache.hertzbeat.templatehub.model.DAO.AuthResourceDao; +import org.apache.hertzbeat.templatehub.model.DAO.AuthRoleDao; +import org.apache.hertzbeat.templatehub.model.DAO.AuthRoleResourceBindDao; +import org.apache.hertzbeat.templatehub.model.DO.AuthResourceDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleDO; +import org.apache.hertzbeat.templatehub.model.DO.AuthRoleResourceBindDO; +import org.apache.hertzbeat.templatehub.service.RoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +/** + * @author tomsun28 + * @date 13:10 2019-08-04 + */ +@Service +@Transactional(rollbackFor = Exception.class) +public class RoleServiceImpl implements RoleService { + + @Autowired + private AuthRoleDao authRoleDao; + + @Autowired + private AuthResourceDao authResourceDao; + + @Autowired + private AuthRoleResourceBindDao roleResourceBindDao; + + @Autowired + private TreePathRoleMatcher treePathRoleMatcher; + + @Override + public Long getRoleIdByCode(String code) { + Long l = authRoleDao.queryIdByCode(code); + if (l == null) { + return null; + } + return l; + } + + @Override + public boolean isRoleExist(AuthRoleDO authRole) { + AuthRoleDO role = AuthRoleDO.builder() + .name(authRole.getName()).code(authRole.getCode()).build(); + return authRoleDao.exists(Example.of(role)); + } + + @Override + public boolean addRole(AuthRoleDO authRole) { + if (isRoleExist(authRole)) { + return false; + } else { + authRoleDao.saveAndFlush(authRole); + return true; + } + } + + @Override + public boolean updateRole(AuthRoleDO authRole) { + if (authRoleDao.existsById(authRole.getId())) { + authRoleDao.saveAndFlush(authRole); + return true; + } else { + return false; + } + } + + @Override + public boolean deleteRole(Long roleId) { + if (authRoleDao.existsById(roleId)) { + authRoleDao.deleteById(roleId); + return true; + } else { + return false; + } + } + + @Override + public Optional> getAllRole() { + List roleList = authRoleDao.findAll(); + return Optional.of(roleList); + } + + @Override + public Page getPageRole(Integer currentPage, Integer pageSize) { + PageRequest pageRequest = PageRequest.of(currentPage, pageSize); + return authRoleDao.findAll(pageRequest); + } + + @Override + public Page getPageResourceOwnRole(Long roleId, Integer currentPage, Integer pageSize) { + PageRequest pageRequest = PageRequest.of(currentPage, pageSize, Sort.Direction.ASC, "id"); + return authResourceDao.findRoleOwnResource(roleId, pageRequest); + } + + @Override + public Page getPageResourceNotOwnRole(Long roleId, Integer currentPage, Integer pageSize) { + PageRequest pageRequest = PageRequest.of(currentPage, pageSize, Sort.Direction.ASC, "id"); + return authResourceDao.findRoleNotOwnResource(roleId, pageRequest); + } + + @Override + public void authorityRoleResource(Long roleId, Long resourceId) { + // Determine whether this resource and role exist + if (!authRoleDao.existsById(roleId) || !authResourceDao.existsById(resourceId)) { + throw new DataConflictException("roleId or resourceId not exist"); + } + // insert it in database, if existed the unique index will work + AuthRoleResourceBindDO bind = AuthRoleResourceBindDO + .builder().roleId(roleId).resourceId(resourceId).build(); + roleResourceBindDao.saveAndFlush(bind); + // refresh resource path data tree + treePathRoleMatcher.rebuildTree(); + } + + @Override + public void deleteAuthorityRoleResource(Long roleId, Long resourceId) { + roleResourceBindDao.deleteRoleResourceBind(roleId, resourceId); + // refresh resource path data tree + treePathRoleMatcher.rebuildTree(); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/StarServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/StarServiceImpl.java new file mode 100644 index 00000000000..e1f98e33b5e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/StarServiceImpl.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.model.DAO.StarDao; +import org.apache.hertzbeat.templatehub.model.DAO.TemplateDao; +import org.apache.hertzbeat.templatehub.model.DAO.VersionDao; +import org.apache.hertzbeat.templatehub.model.DO.StarDO; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.service.StarService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +public class StarServiceImpl implements StarService { + + @Autowired + StarDao starDao; + + @Autowired + VersionDao versionDao; + @Autowired + private TemplateDao templateDao; + + @Override + public int starTemplate(int userId, int templateId, String nowTime) { + + StarDO starDO = new StarDO(); + starDO.setId(0); + starDO.setUserId(userId); + starDO.setTemplateId(templateId); + starDO.setCreateTime(nowTime); + starDO.setIsDel(0); + + StarDO save = starDao.save(starDO); + if(save.getId()==0) { + return 0; + } + + return 1; + } + + @Override + public boolean assertTemplateIdIsStarByUser(int userId, int templateId) { + return starDao.existsStarByTemplateIdAndUserIdAndIsDel(templateId,userId,0); + } + + @Override + public List getTemplateByUserStar(int userId, int isDel) { + return starDao.queryTemplateIdByUserAndIsDel(userId, isDel); + } + + @Override + public Page getPageByUserStar(int userId, int isCancel, int isDel, int offShelf, int page, int size) { + Pageable pageable= PageRequest.of(page, size); + return templateDao.queryPageByUserStar(userId, isCancel, isDel, offShelf,pageable); + } + + @Override + public Boolean cancelStarByUser(int userId, int templateId) { + int i = starDao.cancelByUser(1, userId, templateId, 0); + return i != 0; + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TagServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TagServiceImpl.java new file mode 100644 index 00000000000..111d77fc63c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TagServiceImpl.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.service.TagService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class TagServiceImpl implements TagService { + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateServiceImpl.java new file mode 100644 index 00000000000..86b6b78ebbe --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateServiceImpl.java @@ -0,0 +1,375 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.exception.HertzbeatTemplateHubException; +import org.apache.hertzbeat.templatehub.model.DAO.TemplateDao; +import org.apache.hertzbeat.templatehub.model.DAO.VersionDao; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.apache.hertzbeat.templatehub.service.FileStorageService; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Slf4j +@Service +public class TemplateServiceImpl implements TemplateService { + + @Autowired + VersionService versionService; + + @Autowired + TemplateDao templateDao; + + @Autowired + VersionDao versionDao; + + private final FileStorageService fileStorageService; + + @Autowired + public TemplateServiceImpl(FileStorageService fileStorageService) { + this.fileStorageService = fileStorageService; + } + + @Transactional + @Override + public boolean upload(TemplateDto templateDto, MultipartFile file) { + + TemplateDO templateDO =new TemplateDO(); + templateDO.setId(0); + templateDO.setName(templateDto.getName()); + templateDO.setDescription(templateDto.getDescription()); + templateDO.setLatest(0); + templateDO.setUser(templateDto.getUserId()); + templateDO.setCategoryId(templateDto.getCategoryId()); + templateDO.setTag(0); + templateDO.setDownload(0); + templateDO.setStar(0); + templateDO.setCreateTime(templateDto.getCreate_time()); + templateDO.setUpdateTime(templateDto.getUpdate_time()); + templateDO.setOffShelf(0); + templateDO.setIsDel(0); + + VersionDO versionDO =new VersionDO(); + versionDO.setId(0); + versionDO.setVersion(templateDto.getCurrentVersion()); + versionDO.setDescription(templateDto.getDescriptionVersion()); + versionDO.setDownload(0); + versionDO.setStar(0); + versionDO.setCreateTime(templateDto.getCreate_time()); + versionDO.setOffShelf(0); + versionDO.setIsDel(0); + + int count = templateDao.queryCountByNameAndUser(templateDO.getName(), templateDO.getUser()); + if(count>=1){ + int id = templateDao.queryId(templateDO.getName(), templateDO.getUser()); + templateDO.setId(id); + int versionCount = versionDao.queryCountByTemplateAndVersion(id, templateDto.getCurrentVersion()); + if(versionCount>=1){ + throw new HertzbeatTemplateHubException("You already have a same version"); + } + }else{ + TemplateDO templateDONew = templateDao.save(templateDO); + if(templateDONew.getId()==0){ + throw new HertzbeatTemplateHubException("Template data insertion error"); + } + templateDO = templateDONew; + } + + boolean isInsertVersion = versionService.insertVersion(versionDO, templateDO); + + if(!isInsertVersion){ + throw new HertzbeatTemplateHubException("Version information insertion error"); + } + + String path=templateDto.getUserId()+"/"+ templateDO.getId(); + + try { + fileStorageService.uploadFile(file, path, templateDto.getCurrentVersion()+".yml"); + } catch (RuntimeException e) { + throw new RuntimeException(e); + } + + return true; + } + + @Override + public int getCountByIsDelAndOffShelf(int isDel, int offShelf) { + + return templateDao.queryCountByIsDelAndOffShelf(isDel, offShelf); + } + + @Override + public Page getPageByUserId(int userId, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByUserId(userId, 0,pageable); + } + + @Override + public Page getPageByCategory(List categoryIdList, int isDel, int orderOption, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + + if(orderOption==1){ + return templateDao.queryPageByCategory(categoryIdList, isDel, pageable); + }else{ + return templateDao.queryPageByCategory(categoryIdList, isDel, pageable); + } + } + + @Override + public Page getPageByOption(String nameLike, List categoryIdList, int isDel, int orderOption, int page, int size) { + Pageable pageable = PageRequest.of(page, size); + + if(nameLike.isEmpty()){ + if(orderOption==1){ + return templateDao.queryPageByCategory(categoryIdList, isDel, pageable); + }else{ + return templateDao.queryPageByCategory(categoryIdList, isDel, pageable); + } + }else{ + if(orderOption==1){ + return templateDao.queryPageByNameLikeAndCategory(nameLike, categoryIdList, isDel, pageable); + }else{ + return templateDao.queryPageByNameLikeAndCategory(nameLike, categoryIdList, isDel, pageable); + } + } + + } + + @Override + public Page getPageByIsDelOrderByCreateTimeDesc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByCreateTimeDesc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByCreateTimeAsc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByCreateTimeAsc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByUpdateTimeDesc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByUpdateTimeDesc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByUpdateTimeAsc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByUpdateTimeAsc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByStarDesc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByStarDesc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByStarAsc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByStarAsc(isDel, pageable); + } + + @Override + public Page getPageByIsDelOrderByDownloadDesc(int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByDownloadDesc(isDel,pageable); + } + + @Override + public Page getPageByIsDelOrderByDownloadAsc(int isDel, int page, int size) { + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDelOrderByDownloadAsc(isDel, pageable); + } + + @Override + public Page getPageByNameLike(String name, int isDel, int orderOption, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + + if(orderOption==1){ + return templateDao.queryPageByNameLike(isDel, name,pageable); + }else{ + return templateDao.queryPageByNameLike(isDel, name,pageable); + } + } + + @Override + public Page getTemplatesByPage(int isDel, int page, int size) { + Pageable pageable = PageRequest.of(page, size); + return templateDao.queryPageByIsDel(isDel, pageable); + } + + @Override + @Transactional + public Resource downloadTemplate(int ownerId, int templateId, String version, int versionId) { + + if(templateId==0|| Objects.equals(version, "") ||ownerId==0) throw new IllegalArgumentException("id error"); + + String path=ownerId+"/"+templateId; + String fileName=version+".yml"; + + Resource file = fileStorageService.downloadFile(path, fileName); + if(file==null) return null; + + int isOk = templateDao.downloadUpdate(1,templateId); + if(isOk==0) throw new HertzbeatTemplateHubException("Template download error"); + + int isOk2 = versionDao.downloadUpdate(1,versionId); + if(isOk2==0) throw new HertzbeatTemplateHubException("Template download error"); + + return file; + } + + @Override + public boolean deleteTemplate(int ownerId, int templateId, String version) { + + String path=ownerId+"/"+templateId; + fileStorageService.deleteFile(path,version+".yml"); + return true; + } + + @Override + public TemplateDO getTemplate(int templateId) { + return templateDao.findTemplateById(templateId); + } + + @Override + public boolean starTemplate(int templateId) { + Optional byId = templateDao.findById(templateId); + if(byId.isEmpty()){ + return false; + } + TemplateDO templateDO = byId.get(); + templateDO.setStar(templateDO.getStar() + 1); + templateDao.save(templateDO); + + return true; + } + + @Override + public boolean cancelStarTemplate(int templateId) { + int i = templateDao.cancelStarTemplate(1, templateId); + return i == 1; + } + + @Override + public List getAllTemplates() { + + return templateDao.queryAllByIsDel(0); + } + +// @Deprecated +// @Override +// public ResponseEntity>> getAllTemplatesByUserId(int userId) { +// +// List templateDOS = templateDao.queryByUserId(userId, 0); +// +// return ResponseEntity.ok(Message.success(templateDOS)); +// } +// +// @Deprecated +// @Override +// public List getTemplatesByCategory(int categoryId) { +// +// return templateDao.queryByCategory(categoryId, 0); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByCreateTimeDesc(int isDel) { +// +// return templateDao.queryAllByIsDelOrderByCreateTimeDesc(isDel); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByCreateTimeAsc(int isDel) { +// return templateDao.queryAllByIsDelOrderByCreateTimeAsc(isDel); +// } +// +// @Deprecated +// @Override +// public List getPageByIsDelOrderByUpdateTimeAsc(int isDel) { +// return templateDao.getByIsDelOrderByUpdateTimeAsc(isDel); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByUpdateTimeDesc(int isDel) { +// return templateDao.getByIsDelOrderByUpdateTimeDesc(isDel); +// } +// +// @Deprecated +// @Override +// public List getTemplatesByNameLike(String name) { +// +// return templateDao.queryByNameLike(0, name); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByDownloadAsc(int isDel) { +// return templateDao.getByIsDelOrderByDownloadAsc(isDel); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByStarAsc(int isDel) { +// return templateDao.getByIsDelOrderByStarAsc(isDel); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByDownloadDesc(int isDel) { +// return templateDao.getByIsDelOrderByDownloadDesc(isDel); +// } +// +// @Deprecated +// @Override +// public List getByIsDelOrderByStarDesc(int isDel) { +// return templateDao.getByIsDelOrderByStarDesc(isDel); +// } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateTagServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateTagServiceImpl.java new file mode 100644 index 00000000000..ed625ee3ba9 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/TemplateTagServiceImpl.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.service.TemplateTagService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class TemplateTagServiceImpl implements TemplateTagService { + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/UserServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/UserServiceImpl.java new file mode 100644 index 00000000000..810869a7f65 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/UserServiceImpl.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.service.UserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class UserServiceImpl implements UserService { + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/VersionServiceImpl.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/VersionServiceImpl.java new file mode 100644 index 00000000000..ea4dca84467 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/service/impl/VersionServiceImpl.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.service.impl; + +import org.apache.hertzbeat.templatehub.exception.HertzbeatTemplateHubException; +import org.apache.hertzbeat.templatehub.model.DAO.StarDao; +import org.apache.hertzbeat.templatehub.model.DAO.TemplateDao; +import org.apache.hertzbeat.templatehub.model.DAO.VersionDao; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.model.DTO.TemplateDto; +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.service.FileStorageService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Optional; + +@Slf4j +@Service +public class VersionServiceImpl implements VersionService { + + @Autowired + VersionDao versionDao; + + @Autowired + TemplateDao templateDao; + + @Autowired + StarDao starDao; + + private final FileStorageService fileStorageService; + + @Autowired + public VersionServiceImpl(FileStorageService fileStorageService) { + this.fileStorageService = fileStorageService; + } + + @Override + public boolean insertVersion(VersionDO versionDO, TemplateDO templateDO) { + + versionDO.setTemplateId(templateDO.getId()); + + VersionDO insertVersionDO = versionDao.save(versionDO); + if(insertVersionDO.getId()==0){ + return false; + } + + //Update the latest version in the template file data table + int versionId= insertVersionDO.getId(); + templateDO.setLatest(versionId); + int updateTemplate = templateDao.updateTemplate(templateDO.getLatest(), templateDO.getId()); + + return updateTemplate == 1; + } + + @Deprecated + @Override + public List getVersions(int templateId) { + + return versionDao.queryVersionByTemplateId(templateId); + } + + @Override + public Page getVersionPageByTemplate(int templateId, int isDel, int page, int size) { + + Pageable pageable = PageRequest.of(page, size); + + return versionDao.queryPageByTemplateId(templateId, isDel, pageable); + } + + @Transactional + @Override + public boolean upload(TemplateDto templateDto, MultipartFile file) { + //Generate Template entity + TemplateDO templateDO =templateDao.findTemplateById(templateDto.getId()); + + //Generate version entity + VersionDO versionDO =new VersionDO(); + versionDO.setId(0); + versionDO.setVersion(templateDto.getCurrentVersion()); + versionDO.setDescription(templateDto.getDescriptionVersion()); + versionDO.setDownload(0); + versionDO.setCreateTime(templateDto.getCreate_time()); + versionDO.setOffShelf(0); + versionDO.setIsDel(0); + + + //Check the version table of this template to see if there are any duplicate versions + int versionCount = versionDao.queryCountByTemplateAndVersion(templateDO.getId(), templateDto.getCurrentVersion()); + if(versionCount>=1){ + throw new HertzbeatTemplateHubException("same version"); + } + + //Insert version information + boolean isInsertVersion = insertVersion(versionDO, templateDO); + + if(!isInsertVersion){ + throw new HertzbeatTemplateHubException("Version information insertion error"); + } + + String path=templateDto.getUserId()+"/"+ templateDO.getId(); + + try { + fileStorageService.uploadFile(file, path, templateDto.getCurrentVersion()+".yml"); + } catch (RuntimeException e) { + throw new HertzbeatTemplateHubException(e.getMessage()); + } + + return true; + } + + @Override + public VersionDO getVersion(int versionId) { + Optional byId = versionDao.findById(versionId); + return byId.orElse(null); + } + + @Override + public VersionDO getLatestVersion(int templateId) { + return versionDao.queryLatestByTemplate(templateId); + } + +// @Override +// public boolean startVersion(int versionId) { +// +// Optional byId = versionDao.findById(versionId); +// if(byId.isEmpty()){ +// return false; +// } +// Version version = byId.get(); +// version.setStar(version.getStar() + 1); +// versionDao.save(version); +// +// return true; +// } + +// @Override +// public int cancelStarVersion(int versionId) { +// Optional byId = versionDao.findById(versionId); +// if(byId.isEmpty()){ +// return 0; +// } +// int i = versionDao.cancelStarVersion(1, versionId); +// if(i!=1){ +// return 0; +// } +// return byId.get().getTemplateId(); +// } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/SurenessFilterExample.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/SurenessFilterExample.java new file mode 100644 index 00000000000..e220d00bb50 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/SurenessFilterExample.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.sureness; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.usthe.sureness.mgt.SurenessSecurityManager; +import com.usthe.sureness.processor.exception.*; +import com.usthe.sureness.subject.SubjectSum; +import com.usthe.sureness.util.SurenessContextHolder; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.hertzbeat.templatehub.sureness.processor.RefreshExpiredTokenException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import jakarta.servlet.*; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Map; + +@Order(1) +@Component +@WebFilter(filterName = "SurenessFilterExample", urlPatterns = "/*", asyncSupported = true) +public class SurenessFilterExample implements Filter { + + /** logger **/ + private static final Logger logger = LoggerFactory.getLogger(SurenessFilterExample.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { +// logger.info("SurenessFilterExample init"); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { +// logger.info("SurenessFilterExample doFilter"); + + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + if ("OPTIONS".equals(request.getMethod())){ + response.setStatus(200); + response.setHeader("Access-Control-Allow-Origin","*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, authorization,x-requested-with, *"); + + try { + //获取过滤器链中的filters属性 + Field filtersField = filterChain.getClass().getDeclaredField("filters"); + //反射设置属性可达 + filtersField.setAccessible(true); + //获取filters属性值 + FilterConfig[] filters = (FilterConfig[]) filtersField.get(filterChain); + //跳过过滤器个数记录 + int k = 0; + //遍历所有过滤器 + for (int i = 0; i < filters.length; i++) { + if (filters[i] != null) { + //获取过滤器filterDef属性 + Field filterDefField = filters[i].getClass().getDeclaredField("filterDef"); + filterDefField.setAccessible(true); + //获取filter的class + Field filterClassField = filterDefField.get(filters[i]).getClass().getDeclaredField("filterClass"); + filterClassField.setAccessible(true); + String filterClass = (String) filterClassField.get(filterDefField.get(filters[i])); + String FILTER_REFERENCE1 = "com.usthe.sureness.configuration.SurenessJakartaServletFilter"; + String FILTER_REFERENCE2 = "org.apache.tomcat.websocket.server.WsFilter"; + //跳过指定过滤器处理 + if (FILTER_REFERENCE1.equals(filterClass)||FILTER_REFERENCE2.equals(filterClass)) { + filters[i] = null; + k++; + break; + } + //属性可达关闭 + filterClassField.setAccessible(false); + filterDefField.setAccessible(false); + } + } + //过滤器数组重新赋值,调整移除指定过滤器后过滤器数组 + int index = 0; + for (int i = 0; i < filters.length; i++) { + if (index == 0 && filters[i] == null) { + index = i; + } else if (index != 0 && filters[i] != null) { + filters[index] = filters[i]; + filters[i] = null; + i = index; + index = 0; + } + } + //n值重新赋值 + filtersField.setAccessible(false); + Field n = filterChain.getClass().getDeclaredField("n"); + n.setAccessible(true); + n.set(filterChain, n.getInt(filterChain) - k); + n.setAccessible(false); + logger.info("DemoOncePerRequestFilter end solving"); + } catch (Exception e) { + logger.error("DemoOncePerRequestFilter doFilter exception ", e); + } + + try { + // if ok, doFilter and add subject in request + filterChain.doFilter(servletRequest, servletResponse); + } finally { + SurenessContextHolder.clear(); + } + }else if(request.getRequestURI().contains("template/localFileUpload")){ + response.setStatus(200); + response.setHeader("Access-Control-Allow-Origin","*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, Authorization,authorization"); + try { + // if ok, doFilter and add subject in request + filterChain.doFilter(servletRequest, servletResponse); + } finally { + SurenessContextHolder.clear(); + } + } + else{ + try { + SubjectSum subject = SurenessSecurityManager.getInstance().checkIn(servletRequest); + // You can consider using SurenessContextHolder to bind subject in threadLocal + // if bind, please remove it when end + if (subject != null) { + SurenessContextHolder.bindSubject(subject); + } + } catch (IncorrectCredentialsException | UnknownAccountException | ExpiredCredentialsException e1) { + logger.debug("this request account info is illegal, {}", e1.getMessage()); + responseWrite(ResponseEntity + .status(HttpStatus.UNAUTHORIZED).body("Username or password is incorrect or expired"), servletResponse); + return; + } catch (DisabledAccountException | ExcessiveAttemptsException e2 ) { + logger.debug("the account is disabled, {}", e2.getMessage()); + responseWrite(ResponseEntity + .status(HttpStatus.UNAUTHORIZED).body("Account is disabled"), servletResponse); + return; + } catch (RefreshExpiredTokenException e4) { + logger.debug("this account credential token is expired, return refresh value"); + Map refreshTokenMap = Collections.singletonMap("refresh-token", e4.getMessage()); + responseWrite(ResponseEntity + .status(HttpStatus.UNAUTHORIZED).body(refreshTokenMap), servletResponse); + return; + } catch (UnauthorizedException e5) { + logger.debug("this account can not access this resource, {}", e5.getMessage()); + responseWrite(ResponseEntity + .status(HttpStatus.FORBIDDEN) + .body("This account has no permission to access this resource"), servletResponse); + return; + } catch (RuntimeException e) { + logger.error("other exception happen: ", e); + responseWrite(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(), + servletResponse); + return; + } + try { + // if ok, doFilter and add subject in request + filterChain.doFilter(servletRequest, servletResponse); + } finally { + SurenessContextHolder.clear(); + } + } + + } + + @Override + public void destroy() { +// logger.info("SurenessFilterExample destroy"); + } + + /** + * write response json data + * @param content content + * @param response response + */ + private void responseWrite(ResponseEntity content, ServletResponse response) { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=utf-8"); + ((HttpServletResponse)response).setStatus(content.getStatusCodeValue()); + content.getHeaders().forEach((key, value) -> + ((HttpServletResponse) response).addHeader(key, value.get(0))); + try (PrintWriter printWriter = response.getWriter()) { + if (content.getBody() != null) { + if (content.getBody() instanceof String) { + printWriter.write(content.getBody().toString()); + } else { + ObjectMapper objectMapper = new ObjectMapper(); + printWriter.write(objectMapper.writeValueAsString(content.getBody())); + } + } else { + printWriter.flush(); + } + } catch (IOException e) { + logger.error("responseWrite response error: ", e); + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/processor/RefreshExpiredTokenException.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/processor/RefreshExpiredTokenException.java new file mode 100644 index 00000000000..79b8698f08f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/processor/RefreshExpiredTokenException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.sureness.processor; + +import com.usthe.sureness.processor.exception.SurenessAuthenticationException; + +/** + * refresh token message + * @author tomsun28 + * @date 2020-12-03 23:29 + */ +public class RefreshExpiredTokenException extends SurenessAuthenticationException { + public RefreshExpiredTokenException(String message) { + super(message); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabaseAccountProvider.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabaseAccountProvider.java new file mode 100644 index 00000000000..e59536fe30f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabaseAccountProvider.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.sureness.provider; + +import com.usthe.sureness.provider.SurenessAccount; +import com.usthe.sureness.provider.SurenessAccountProvider; +import org.apache.hertzbeat.templatehub.service.AccountService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * the provider provides account info + * load account info from database + * @author tomsun28 + * @date 22:44 2020-03-02 + */ +@Component +public class DatabaseAccountProvider implements SurenessAccountProvider { + + @Autowired + AccountService accountService; + + @Override + public SurenessAccount loadAccount(String appId) { + return accountService.loadAccount(appId); + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabasePathTreeProvider.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabasePathTreeProvider.java new file mode 100644 index 00000000000..aa45e8aef15 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/sureness/provider/DatabasePathTreeProvider.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.sureness.provider; + +import com.usthe.sureness.matcher.PathTreeProvider; +import com.usthe.sureness.util.SurenessCommonUtil; +import org.apache.hertzbeat.templatehub.service.ResourceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Set; + +/** + * ths provider provides path resources + * load sureness config resource form database + * @author tomsun28 + * @date 16:00 2019-08-04 + */ +@Component +public class DatabasePathTreeProvider implements PathTreeProvider { + + @Autowired + private ResourceService resourceService; + + @Override + public Set providePathData() { + // 从数据库中读取出path信息,取出所有状态为1,即正常的path信息 + Set pathSet = SurenessCommonUtil.attachContextPath(getContextPath(), resourceService.getAllEnableResourcePath()); + return pathSet; + + } + + @Override + public Set provideExcludedResource() { + // 从数据库中读取出path信息,取出所有状态为9,即禁用的path信息 + Set exlResourceSet = SurenessCommonUtil.attachContextPath(getContextPath(), resourceService.getAllDisableResourcePath()); + return exlResourceSet; + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base62Util.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base62Util.java new file mode 100644 index 00000000000..739e7ed00ab --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base62Util.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.util; + +public final class Base62Util { + private static final String BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + private Base62Util() { + } + + public static boolean isBase62(String str) { + if (str == null || str.isEmpty()) { + return false; + } + + for (char c : str.toCharArray()) { + if (BASE62.indexOf(c) == -1) { + return false; + } + } + + return true; + } + + /** + * Long to short + */ + public static String idToShortKey(long id) { + StringBuilder stringBuilder = new StringBuilder(); + if(id==0){ + stringBuilder.append("0"); + return stringBuilder.toString(); + } + while (id > 0) { + stringBuilder.append(BASE62.charAt((int) (id % 62))); + id = id / 62; + } + + return stringBuilder.reverse().toString(); + } + + public static long shortKeyToId(String shortKey) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(shortKey); + while (stringBuilder.length() < 6) { + stringBuilder.append(0); + } + long id = 0; + for (int i = 0; i < shortKey.length(); i++) { + id = id * 62 + BASE62.indexOf(shortKey.charAt(i)); + } + + return id; + } +} + diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base64Util.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base64Util.java new file mode 100644 index 00000000000..a44d7633ea8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/Base64Util.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.util; + +import java.util.Base64; + +/** + * base64 util + */ +public final class Base64Util { + + private Base64Util() { + } + + public static boolean isBase64(String base64) { + + if (base64 == null || base64.isEmpty()) { + return false; + } + + try { + return Base64.getDecoder().decode(base64) != null; + } catch (Exception e) { + return false; + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/JsonUtil.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/JsonUtil.java new file mode 100644 index 00000000000..c1c05355ff6 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/JsonUtil.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; + +import javax.annotation.concurrent.ThreadSafe; + +/** + * json util + */ +@ThreadSafe +@Slf4j +public final class JsonUtil { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private JsonUtil() { + } + + static { + OBJECT_MAPPER + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .registerModule(new JavaTimeModule()); + } + + public static String toJson(Object source) { + if (source == null) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsString(source); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + return null; + } + } + + public static T fromJson(String jsonStr, Class clazz) { + if (!StringUtils.hasText(jsonStr)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(jsonStr, clazz); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + public static T fromJson(String jsonStr, TypeReference type) { + if (!StringUtils.hasText(jsonStr)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(jsonStr, type); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + public static JsonNode fromJson(String jsonStr) { + if (!StringUtils.hasText(jsonStr)) { + return null; + } + try { + return OBJECT_MAPPER.readTree(jsonStr); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * check if the string is a json string + * @param jsonStr json string + * @return true if the string is a json string + */ + + + public static boolean isJsonStr(String jsonStr) { + if (jsonStr == null || jsonStr.trim().isEmpty()) { + return false; + } + jsonStr = jsonStr.trim(); + if (!(jsonStr.startsWith("{") && jsonStr.endsWith("}")) + && !(jsonStr.startsWith("[") && jsonStr.endsWith("]"))) { + return false; + } + try { + OBJECT_MAPPER.readTree(jsonStr); + return true; + } catch (Exception ignored) { + return false; + } + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/ResponseUtil.java b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/ResponseUtil.java new file mode 100644 index 00000000000..578919e2d5c --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/java/org/apache/hertzbeat/templatehub/util/ResponseUtil.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.util; + +import org.apache.hertzbeat.templatehub.constants.CommonConstants; +import org.apache.hertzbeat.templatehub.model.DTO.Message; +import org.springframework.http.ResponseEntity; + +import javax.naming.AuthenticationException; + +/** + * A tool which make the restful response be easy to use + */ +public class ResponseUtil { + public static ResponseEntity> handle(Supplier supplier) { + try { + T result = supplier.get(); + return ResponseEntity.ok(Message.success(result)); + } catch (Exception e) { + byte err = CommonConstants.FAIL_CODE; + if (e.getClass().equals(AuthenticationException.class)) { + err = CommonConstants.LOGIN_FAILED_CODE; + } + return ResponseEntity.ok(Message.fail(err, e.getMessage())); + } + } + + public static ResponseEntity> handle(Runnable runner) { + try { + runner.run(); + return ResponseEntity.ok(Message.success()); + } catch (Exception e) { + byte err = CommonConstants.FAIL_CODE; + if (e.getClass().equals(AuthenticationException.class)) { + err = CommonConstants.LOGIN_FAILED_CODE; + } + return ResponseEntity.ok(Message.fail(err, e.getMessage())); + } + } + + /** + * Supplier interface for getting result + */ + public interface Supplier { + + /** + * Gets a result. + * + * @return a result + */ + T get() throws E; + } + + /** + * Runnable interface for running + */ + public interface Runnable { + + /** + * Run target method. + */ + void run() throws Exception; + } +} diff --git a/template-marketplace/hertzbeat-template-hub/src/main/resources/application.yml b/template-marketplace/hertzbeat-template-hub/src/main/resources/application.yml new file mode 100644 index 00000000000..b3de912b5a2 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/resources/application.yml @@ -0,0 +1,65 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +server: + address: localhost + port: 8080 + servlet: + context-path: /api + +spring: + application: + name: hetzbeat-template-hub + datasource: + url: jdbc:mysql://localhost:3306/hertzbeat_template_hub + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + properties: + hibernate: + hbm2ddl: + auto: update + format_sql: true + show-sql: true + open-in-view: true + +file: + storage: + type: minio + # type: local + +address: http://localhost:8080 + +local: + storage: + path: /path/to/local/storage + +minio: + endpoint: http://127.0.0.1:9000 + accessKey: CMULmgc3rfbnhmOCpXci + secretKey: Mw9wnljHl4RtVBGcipcmDTArdCx75lAwaMJeLXGC + bucketName: hertzbeat-data + + +sureness: + container: jakarta_servlet + auths: + - jwt + jwt: + secret: 'CyaFv0bwq2Eik0jdrKUtsA6bx3sDJeFV643R + LnfKefTjsIfJLBa2YkhEqEGtcHDTNe4CU6+9 + 8tVt4bisXQ13r4N0oxhUZRd3M6EByXIO+SV5 + dKhaX0cs3OC5lCxq20yhmUea6H6JIpSE2Rwp' \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/main/resources/sureness.yml b/template-marketplace/hertzbeat-template-hub/src/main/resources/sureness.yml new file mode 100644 index 00000000000..0c29771226a --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/main/resources/sureness.yml @@ -0,0 +1,29 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +## -- sureness.yml account source -- ## + +# config the resource restful api that need auth protection, base rbac +# rule: api===method===role +# eg: /api/v1/source1===get===[admin] means /api/v2/host===post support role[admin] access. +# eg: /api/v1/source2===get===[] means /api/v1/source2===get can not access by any role. +resourceRole: + + + +# config the resource restful api that need bypass auth protection +# rule: api===method +# eg: /api/v1/source3===get means /api/v1/source3===get can be access by anyone, no need auth. +excludedResource: diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateDOHubApplicationTests.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateDOHubApplicationTests.java new file mode 100644 index 00000000000..6e7ce38e02f --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateDOHubApplicationTests.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class HertzbeatTemplateDOHubApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplicationTests.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplicationTests.java new file mode 100644 index 00000000000..2d587800245 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/HertzbeatTemplateHubApplicationTests.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class HertzbeatTemplateHubApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/config/FileStorageConfigTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/config/FileStorageConfigTest.java new file mode 100644 index 00000000000..6aaa6ed6b13 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/config/FileStorageConfigTest.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.config; + +import org.junit.jupiter.api.Test; +public class FileStorageConfigTest { + + @Test + public void testFileStorageServiceWithMinio() { + } + + @Test + public void testFileStorageServiceWithLocal() { + } + + @Test + public void testFileStorageServiceWithInvalidType() { + } +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryControllerTest.java new file mode 100644 index 00000000000..add62d15e83 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryControllerTest.java @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.entity.Category; +import org.apache.hertzbeat.templatehub.service.CategoryService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Test case for {@link CategoryController} + */ +@ExtendWith(MockitoExtension.class) +class CategoryControllerTest { + + @InjectMocks + private CategoryController categoryController; + + @Mock + private CategoryService categoryService; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = standaloneSetup(categoryController).build(); + } + @Test + public void testAddCategory_ValidInput() throws Exception { + + when(categoryService.addCategory(any(String.class), any(String.class), any(String.class))).thenReturn(true); + + mockMvc.perform(post("/category/upload/testName") + .param("description", "Test description") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testAddCategory_InvalidInput() throws Exception { + mockMvc.perform(post("/category/upload/{name}","testName") + .param("description", "")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testModifyCategory_ValidInput() throws Exception { + // Mock the category service method + when(categoryService.modifyCategory(anyInt(), any(String.class), any(String.class), any(String.class))).thenReturn(true); + + // Perform the request + mockMvc.perform(post("/category/modify/1") + .param("name", "Updated Name") + .param("description", "Updated description") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testModifyCategory_InvalidInput() throws Exception { + mockMvc.perform(post("/category/modify/0") + .param("name", "") + .param("description", "")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testDeleteCategory_ValidId() throws Exception { + when(categoryService.deleteCategory(anyInt())).thenReturn(true); + + mockMvc.perform(delete("/category/delete/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testDeleteCategory_InvalidId() throws Exception { + mockMvc.perform(delete("/category/delete/0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetAllCategory_ValidInput() throws Exception { + List categories = Collections.singletonList(new Category()); + when(categoryService.getAllCategoryByIsDel(anyInt())).thenReturn(categories); + + mockMvc.perform(get("/category/all/0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data").isArray()); + } + + @Test + public void testGetAllCategory_InvalidInput() throws Exception { + mockMvc.perform(get("/category/all/2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetCategoryPageByIsDel_ValidInput() throws Exception { + List categories = new ArrayList<>(); + categories.add(new Category()); + Page categoryPage = new PageImpl<>(categories); + + when(categoryService.getPageByIsDel(anyInt(), anyInt(), anyInt())).thenReturn(categoryPage); + + mockMvc.perform(get("/category/page/isDel/0?page=0&size=10")); + + verify(categoryService,times(1)).getPageByIsDel(anyInt(), anyInt(), anyInt()); + } + + @Test + public void testGetCategoryPageByIsDel_InvalidInput() throws Exception { + mockMvc.perform(get("/category/page/isDel/2?page=-1&size=0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryDOControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryDOControllerTest.java new file mode 100644 index 00000000000..08c01d5c7e3 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/CategoryDOControllerTest.java @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.DO.CategoryDO; +import org.apache.hertzbeat.templatehub.service.CategoryService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Test case for {@link CategoryController} + */ +@ExtendWith(MockitoExtension.class) +class CategoryDOControllerTest { + + @InjectMocks + private CategoryController categoryController; + + @Mock + private CategoryService categoryService; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = standaloneSetup(categoryController).build(); + } + @Test + public void testAddCategory_ValidInput() throws Exception { + + when(categoryService.addCategory(any(String.class), any(String.class), any(String.class))).thenReturn(true); + + mockMvc.perform(post("/category/upload/testName") + .param("description", "Test description") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testAddCategory_InvalidInput() throws Exception { + mockMvc.perform(post("/category/upload/{name}","testName") + .param("description", "")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testModifyCategory_ValidInput() throws Exception { + // Mock the category service method + when(categoryService.modifyCategory(anyInt(), any(String.class), any(String.class), any(String.class))).thenReturn(true); + + // Perform the request + mockMvc.perform(post("/category/modify/1") + .param("name", "Updated Name") + .param("description", "Updated description") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testModifyCategory_InvalidInput() throws Exception { + mockMvc.perform(post("/category/modify/0") + .param("name", "") + .param("description", "")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testDeleteCategory_ValidId() throws Exception { + when(categoryService.deleteCategory(anyInt())).thenReturn(true); + + mockMvc.perform(delete("/category/delete/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testDeleteCategory_InvalidId() throws Exception { + mockMvc.perform(delete("/category/delete/0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetAllCategory_ValidInput() throws Exception { + List categories = Collections.singletonList(new CategoryDO()); + when(categoryService.getAllCategoryByIsDel(anyInt())).thenReturn(categories); + + mockMvc.perform(get("/category/all/0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data").isArray()); + } + + @Test + public void testGetAllCategory_InvalidInput() throws Exception { + mockMvc.perform(get("/category/all/2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetCategoryPageByIsDel_ValidInput() throws Exception { + List categories = new ArrayList<>(); + categories.add(new CategoryDO()); + Page categoryPage = new PageImpl<>(categories); + + when(categoryService.getPageByIsDel(anyInt(), anyInt(), anyInt())).thenReturn(categoryPage); + + mockMvc.perform(get("/category/page/isDel/0?page=0&size=10")); + + verify(categoryService,times(1)).getPageByIsDel(anyInt(), anyInt(), anyInt()); + } + + @Test + public void testGetCategoryPageByIsDel_InvalidInput() throws Exception { + mockMvc.perform(get("/category/page/isDel/2?page=-1&size=0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/ShareControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/ShareControllerTest.java new file mode 100644 index 00000000000..a8544d6b508 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/ShareControllerTest.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.model.DO.VersionDO; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.apache.hertzbeat.templatehub.util.Base62Util; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Test case for {@link ShareController} + */ +@ExtendWith(MockitoExtension.class) +class ShareControllerTest { + + private MockMvc mockMvc; + + @Mock + private TemplateService templateService; + + @Mock + private VersionService versionService; + + @InjectMocks + private ShareController shareController; + + private final String serverAddress = "localhost"; + private final String serverPort = "8080"; + private final String contextPath = "/api"; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + this.mockMvc = MockMvcBuilders.standaloneSetup(shareController).build(); + + ReflectionTestUtils.setField(shareController, "serverAddress", serverAddress); + ReflectionTestUtils.setField(shareController, "serverPort", serverPort); + ReflectionTestUtils.setField(shareController, "contextPath", contextPath); + } + + @Test + public void testGetShareURL_ValidVersion() throws Exception { + int versionId = 1; + + VersionDO mockVersionDO = new VersionDO(); + + String expectedUrl = "http://" + serverAddress + ":" + serverPort + contextPath + "/share/download/" + + Base62Util.idToShortKey(versionId + 100000000); + + when(versionService.getVersion(versionId)).thenReturn(mockVersionDO); + + this.mockMvc.perform(get("/share/getShareURL/{versionId}",versionId) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.msg").value(expectedUrl)); + } + + @Test + public void testDownloadShare_ValidKey() throws Exception { + String key = Base62Util.idToShortKey(100000001); + int versionId = 1; + VersionDO mockVersionDO = new VersionDO(); + mockVersionDO.setId(versionId); + mockVersionDO.setVersion("v1.0.0"); + mockVersionDO.setTemplateId(1); + + TemplateDO mockTemplateDO = new TemplateDO(); + mockTemplateDO.setId(1); + mockTemplateDO.setUser(1); + + Resource mockResource = mock(Resource.class); + + when(versionService.getVersion(versionId)).thenReturn(mockVersionDO); + when(templateService.getTemplate(1)).thenReturn(mockTemplateDO); + when(templateService.downloadTemplate(mockVersionDO.getId(), mockTemplateDO.getId(), mockVersionDO.getVersion(), mockVersionDO.getId())).thenReturn(mockResource); + + this.mockMvc.perform(get("/share/download/{key}", key) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + mockVersionDO.getVersion() + ".yml\"")) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)); + + verify(versionService).getVersion(versionId); + verify(templateService).getTemplate(1); + verify(templateService).downloadTemplate(mockVersionDO.getId(), mockTemplateDO.getId(), mockVersionDO.getVersion(), mockVersionDO.getId()); + } + + @Test + public void testDownloadShare_InvalidKey() throws Exception { + String invalidKey = "+0"; + + this.mockMvc.perform(get("/api/share/download/{key}", invalidKey) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); + } +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarControllerTest.java new file mode 100644 index 00000000000..c4a1e59ae8d --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarControllerTest.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.entity.Version; +import org.apache.hertzbeat.templatehub.service.StarService; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Test case for {@link StarController} + */ +@ExtendWith(MockitoExtension.class) +class StarControllerTest { + + @InjectMocks + private StarController starController; + + @Mock + private StarService starService; + + @Mock + private VersionService versionService; + + @Mock + private TemplateService templateService; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = standaloneSetup(starController).build(); + } + + @Deprecated + @Test + public void testGetAllVersionByUserStar_ValidUserId() throws Exception { + List versions = Collections.singletonList(new Version()); + when(starService.getVersionByUserStar(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(versions); + + mockMvc.perform(get("/star/{user}", 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data").isArray()); + } + + @Test + public void testGetAllVersionByUserStar_InvalidUserId() throws Exception { + mockMvc.perform(get("/star/{user}", -1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetVersionPageByUserStar_ValidInput() throws Exception { + List versions = new ArrayList<>(); + versions.add(new Version()); + Page versionPage = new PageImpl<>(versions); + + when(starService.getPageByUserStar(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(versionPage); + + mockMvc.perform(get("/star/page/user/{user}", 1) + .param("page", "0") + .param("size", "10")); + + verify(starService,times(1)).getPageByUserStar(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); + } + + @Test + public void testGetVersionPageByUserStar_InvalidUserId() throws Exception { + mockMvc.perform(get("/star/page/user/{user}", -1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); // Expect failure code + } + + @Test + public void testCancelStar_ValidInput() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); + when(versionService.cancelStarVersion(anyInt())).thenReturn(1); + when(templateService.cancelStarTemplate(anyInt())).thenReturn(true); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testCancelStar_InvalidUserId() throws Exception { + mockMvc.perform(post("/star/cancel/{user}", -1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_InvalidVersionId() throws Exception { + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "-1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelStarServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(false); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelVersionServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); + when(versionService.cancelStarVersion(anyInt())).thenReturn(0); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelTemplateServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); + when(versionService.cancelStarVersion(anyInt())).thenReturn(1); + when(templateService.cancelStarTemplate(anyInt())).thenReturn(false); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarDOControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarDOControllerTest.java new file mode 100644 index 00000000000..90af15fbc1e --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/StarDOControllerTest.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import org.apache.hertzbeat.templatehub.model.DO.TemplateDO; +import org.apache.hertzbeat.templatehub.service.StarService; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.apache.hertzbeat.templatehub.service.VersionService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Test case for {@link StarController} + */ +@ExtendWith(MockitoExtension.class) +class StarDOControllerTest { + + @InjectMocks + private StarController starController; + + @Mock + private StarService starService; + + @Mock + private VersionService versionService; + + @Mock + private TemplateService templateService; + + private MockMvc mockMvc; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = standaloneSetup(starController).build(); + } + + @Test + public void testGetAllVersionByUserStar_InvalidUserId() throws Exception { + mockMvc.perform(get("/star/{user}", -1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testGetVersionPageByUserStar_ValidInput() throws Exception { + List templateDOS = new ArrayList<>(); + templateDOS.add(new TemplateDO()); + Page templatePage = new PageImpl<>(templateDOS); + + when(starService.getPageByUserStar(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(templatePage); + + mockMvc.perform(get("/star/page/user/{user}", 1) + .param("page", "0") + .param("size", "10")); + + verify(starService,times(1)).getPageByUserStar(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt()); + } + + @Test + public void testGetVersionPageByUserStar_InvalidUserId() throws Exception { + mockMvc.perform(get("/star/page/user/{user}", -1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); // Expect failure code + } + + @Test + public void testCancelStar_ValidInput() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); +// when(versionService.cancelStarVersion(anyInt())).thenReturn(1); + when(templateService.cancelStarTemplate(anyInt())).thenReturn(true); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + } + + @Test + public void testCancelStar_InvalidUserId() throws Exception { + mockMvc.perform(post("/star/cancel/{user}", -1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_InvalidVersionId() throws Exception { + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "-1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelStarServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(false); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelVersionServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); + when(templateService.cancelStarTemplate(anyInt())).thenReturn(false); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("templateId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + + @Test + public void testCancelStar_CancelTemplateServiceFailed() throws Exception { + // Mock the service methods + when(starService.cancelStarByUser(anyInt(), anyInt())).thenReturn(true); + when(templateService.cancelStarTemplate(anyInt())).thenReturn(false); + + mockMvc.perform(post("/star/cancel/{user}", 1) + .param("versionId", "1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(15)); + } + +} \ No newline at end of file diff --git a/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/TemplateControllerTest.java b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/TemplateControllerTest.java new file mode 100644 index 00000000000..9a802573af8 --- /dev/null +++ b/template-marketplace/hertzbeat-template-hub/src/test/java/org/apache/hertzbeat/templatehub/controller/TemplateControllerTest.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.hertzbeat.templatehub.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.hertzbeat.templatehub.model.dto.TemplateDto; +import org.apache.hertzbeat.templatehub.model.entity.Template; +import org.apache.hertzbeat.templatehub.service.TemplateService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; + +/** + * Test case for {@link TemplateController} + */ +@ExtendWith(MockitoExtension.class) +class TemplateControllerTest { + + @InjectMocks + private TemplateController templateController; + + @Mock + private TemplateService templateService; + + private MockMvc mockMvc; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = standaloneSetup(templateController).build(); + } + + @Test + void testUploadTemplate_WithEmptyFileAndString_ShouldReturnParamsError() throws Exception { + this.mockMvc.perform(multipart("/template/upload") + .file("file", new byte[0]) + .param("templateDto", "") + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.msg").value("params error")); + + verify(templateService, never()).upload(any(), any()); + } + + @Test + void testUploadTemplate_WithValidInputs_ShouldReturnUploadSuccess() throws Exception { + TemplateDto dto = new TemplateDto(); + dto.setUserId(1); + dto.setName("Test Template"); + dto.setCurrentVersion("1.0"); + + String jsonString = objectMapper.writeValueAsString(dto); + when(templateService.upload(any(), any())).thenReturn(true); + + this.mockMvc.perform(multipart("/template/upload") + .file("file", new byte[1]) + .param("templateDto", jsonString) + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.msg").value("upload success")); + + verify(templateService, times(1)).upload(any(), any()); + } + + @Test + void testGetCountByIsDelAndOffshelf_WithValidParams_ShouldReturnCount() throws Exception { + when(templateService.getCountByIsDelAndOffShelf(0, 1)).thenReturn(5); + + this.mockMvc.perform(MockMvcRequestBuilders.get("/template/count/{isDel}/{offShelf}", 0, 1)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data").value(5)) + .andReturn(); + + verify(templateService, times(1)).getCountByIsDelAndOffShelf(0, 1); + } + + @Test + void testGetTemplatePageByCategory_WithValidParams_ShouldReturnTemplates() throws Exception { + + List