From 61bba2b67e0dda733f34ffae7c25ffcd69f10bdc Mon Sep 17 00:00:00 2001 From: "manhng132@gmail.com" Date: Thu, 10 Nov 2022 07:00:16 +0700 Subject: [PATCH] deloy --- .dependabot/config.yml | 45 ++ .github/CODEOWNERS | 1 + .github/CODE_OF_CONDUCT.md | 46 ++ .github/ISSUE_TEMPLATE/bug_report.yaml | 49 ++ .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/PULL_REQUEST_TEMPLATE.md | 22 + .github/badges/twitter.svg | 1 + .github/dependabot.yml | 31 + .github/graphql-inspector.yaml | 11 + .github/stale.yml | 60 ++ .github/workflows/bump-dependencies.yml | 37 ++ .github/workflows/codeql-analysis.yml | 54 ++ .github/workflows/graphql-inspector.yml | 16 + .github/workflows/migrations-perf-test.yml | 74 +++ .github/workflows/publish-containers.rst | 43 ++ .github/workflows/publish-containers.yml | 154 +++++ .github/workflows/pytest.yml | 105 +++ .github/workflows/test-env-cleanup.yml | 37 ++ .github/workflows/test-env-deploy.yml | 66 ++ .../test-migrations-compatibility.yml | 65 ++ .rubocop.yml | 8 + .rubocop_todo.yml | 194 ++++++ .vscode/extensions.json | 12 + .vscode/settings.json | 8 + LICENSE | 30 + app/controllers/api/concerns/.keep | 0 .../api/concerns/errors_handler.rb | 60 -- .../api/concerns/responses_handler.rb | 74 --- app/controllers/api/sessions_controller.rb | 3 + app/helpers/api_sessions_helper.rb | 85 --- app/services/jwt/user/decode_token_service.rb | 8 +- app/services/jwt/user/encode_token_service.rb | 2 +- app/views/api/sessions/create.json.jbuilder | 11 +- app/views/api/sessions/index.json.jbuilder | 51 +- config/credentials.yml.enc | 2 +- config/initializers/cors.rb | 8 + editor.swagger.io.yaml | 626 ++++++++++++++++++ maearon.talentapi_collection.json | 598 +++++++++++++++++ 39 files changed, 2491 insertions(+), 231 deletions(-) create mode 100644 .dependabot/config.yml create mode 100644 .github/CODEOWNERS create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/badges/twitter.svg create mode 100644 .github/dependabot.yml create mode 100644 .github/graphql-inspector.yaml create mode 100644 .github/stale.yml create mode 100644 .github/workflows/bump-dependencies.yml create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/graphql-inspector.yml create mode 100644 .github/workflows/migrations-perf-test.yml create mode 100644 .github/workflows/publish-containers.rst create mode 100644 .github/workflows/publish-containers.yml create mode 100644 .github/workflows/pytest.yml create mode 100644 .github/workflows/test-env-cleanup.yml create mode 100644 .github/workflows/test-env-deploy.yml create mode 100644 .github/workflows/test-migrations-compatibility.yml create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json delete mode 100644 app/controllers/api/concerns/.keep delete mode 100644 app/controllers/api/concerns/errors_handler.rb delete mode 100644 app/controllers/api/concerns/responses_handler.rb delete mode 100644 app/helpers/api_sessions_helper.rb create mode 100644 editor.swagger.io.yaml create mode 100644 maearon.talentapi_collection.json diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 00000000000..f63922cb3d9 --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,45 @@ +version: 1 +update_configs: + - package_manager: "ruby:bundler" + directory: "/" + update_schedule: "live" + automerged_updates: + - match: + dependency_name: "spree*" + update_type: "semver:patch" + - match: + dependency_name: "rails" + update_type: "semver:patch" + - match: + dependency_name: "rubocop*" + - match: + dependency_name: "puma" + - match: + dependency_name: "rack*" + - match: + dependency_name: "sentry-raven" + - match: + dependency_name: "scout_apm" + - match: + dependency_name: "flipper*" + update_type: "semver:minor" + - match: + dependency_name: "sidekiq" + update_type: "semver:minor" + - match: + dependency_name: "aws-sdk-s3" + update_type: "semver:minor" + - match: + dependency_name: "mini_racer" + - match: + dependency_name: "sass-rails" + - match: + dependency_name: "awesome_print" + - match: + dependency_name: "pry*" + - match: + dependency_name: "rspec*" + - match: + dependency_name: "webdrivers" + - match: + dependency_name: "sendgrid-actionmailer" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..ddb526b7a65 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +.github/workflows/* @saleor/sre diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..214ad645594 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello+community@saleor.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 00000000000..087c57f3c4c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,49 @@ +name: Bug report +description: Create a bug report +title: "Bug: " +labels: ["bug", "triage"] + +body: + - type: textarea + id: goal + attributes: + label: What are you trying to achieve? + description: Describe your goal, use case, or provide context of your problem from the business point of view. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce the problem + description: Reproduction steps starting with an empty database. You can use a free Saleor Cloud environment as a quick starting point. + placeholder: | + 1. Create a product with two attributes… + 2. … + 3. Run `…` + 4. See that it failed with… + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: What did you expect to happen? + description: Describe why the behavior described earlier is incorrect. + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs + description: Include any logs from the console, screenshots, and any API queries or responses that could help us understand the problem. Make sure to omit any personal identifiable information or data sensitive to your business. + validations: + required: false + - type: textarea + id: environment + attributes: + label: Environment + description: Provide some information about your environment. + value: | + Saleor version: … + OS and version: … + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..1eed3dfccb1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 💬 GitHub Discussions + url: https://github.com/saleor/saleor/discussions + about: If you have a support question or need help getting Saleor to work, please use GitHub Discussions. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..303caf3bc53 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: Feature request +assignees: '' + +--- + +### What I'm trying to achieve +… + +### Describe a proposed solution +... + +### Other solutions I've tried and won't work +… + +### Screenshots or mockups + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..02e9c60f2aa --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,22 @@ +I want to merge this change because... + + + +# Impact + +* [ ] New migrations +* [ ] New/Updated API fields or mutations +* [ ] Deprecated API fields or mutations +* [ ] Removed API types, fields, or mutations +* [ ] Documentation needs to be updated + +# Pull Request Checklist + + + +* [ ] Privileged queries and mutations are guarded by proper permission checks +* [ ] Database queries are optimized and the number of queries is constant +* [ ] Database migration files are up to date +* [ ] The changes are tested +* [ ] GraphQL schema and type definitions are up to date +* [ ] Changes are mentioned in the changelog diff --git a/.github/badges/twitter.svg b/.github/badges/twitter.svg new file mode 100644 index 00000000000..5fd5792ff07 --- /dev/null +++ b/.github/badges/twitter.svg @@ -0,0 +1 @@ +Follow @getsaleorFollow @getsaleor diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..ac8622ba7bb --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,31 @@ +version: 2 +updates: +- package-ecosystem: pip + directory: "/" + schedule: + interval: weekly + time: "04:00" + open-pull-requests-limit: 10 + ignore: + - dependency-name: django-graphql-jwt + versions: + - "> 0.3.0" + - dependency-name: black + versions: + - 21.4b0 + - dependency-name: adyen + versions: + - 5.0.0 + - 5.1.0 + - dependency-name: faker + versions: + - 7.0.1 + - dependency-name: django-countries + versions: + - "7.1" + - dependency-name: mypy + versions: + - "0.812" + - dependency-name: pytest-xdist + versions: + - 2.2.1 diff --git a/.github/graphql-inspector.yaml b/.github/graphql-inspector.yaml new file mode 100644 index 00000000000..9c86fa70c52 --- /dev/null +++ b/.github/graphql-inspector.yaml @@ -0,0 +1,11 @@ +branch: "main" +schema: "saleor/graphql/schema.graphql" +diff: + # Pull Request annotations + annotations: true + # Merge Pull Request's branch with the target branch to get the schema + experimental_merge: true + # Label to mark Pull Request introducing breaking changes as safe and expected + approveLabel: 'approved-breaking-change' + # Limit a list of changes in summary + summaryLimit: 200 diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000000..4584c575beb --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,60 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 7 + +# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) +onlyLabels: [] + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - bug + - blocker + - backlog + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Set to true to ignore issues with an assignee (defaults to false) +exemptAssignees: false + +# Label to use when marking as stale +staleLabel: stale + +# Comment to post when marking as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +# Comment to post when removing the stale label. +# unmarkComment: > +# Your comment here. + +# Comment to post when closing a stale Issue or Pull Request. +# closeComment: > +# Your comment here. + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 +# Limit to only `issues` or `pulls` +# only: issues + +# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': +# pulls: +# daysUntilStale: 30 +# markComment: > +# This pull request has been automatically marked as stale because it has not had +# recent activity. It will be closed if no further activity occurs. Thank you +# for your contributions. + +# issues: +# exemptLabels: +# - confirmed diff --git a/.github/workflows/bump-dependencies.yml b/.github/workflows/bump-dependencies.yml new file mode 100644 index 00000000000..6824a2bc4fa --- /dev/null +++ b/.github/workflows/bump-dependencies.yml @@ -0,0 +1,37 @@ +name: Bump dependencies + +on: + workflow_dispatch: + schedule: + - cron: '0 8 * * 1' # At 08:00 on Monday. + +jobs: + bump-dependencies: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + + - run: python -m pip install poetry pre-commit + - run: poetry lock + - run: poetry export --without-hashes --with dev -f requirements.txt -o requirements_dev.txt + - run: poetry export -f requirements.txt --without-hashes -o requirements.txt + - run: pre-commit autoupdate + - run: git status + + - name: Create Pull Request + uses: peter-evans/create-pull-request@18f7dc018cc2cd597073088f7c7591b9d1c02672 + with: + token: ${{ secrets.TRIGGER_WORKFLOW_KEY }} + branch: bump-dependencies + delete-branch: true + commit-message: Bump dependencies + title: 'Bump dependencies' + body: | + Weekly update of backend dependencies. + labels: | + :robot: bot + test deployment diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000000..43f030bd46f --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,54 @@ +name: "CodeQL" + +on: + push: + branches: [main, ] + pull_request: + # The branches below must be a subset of the branches above + branches: [main] + schedule: + - cron: '0 3 * * 6' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/graphql-inspector.yml b/.github/workflows/graphql-inspector.yml new file mode 100644 index 00000000000..184fb5b4bfc --- /dev/null +++ b/.github/workflows/graphql-inspector.yml @@ -0,0 +1,16 @@ +name: GraphQL Inspector + +on: + push: + paths: [ "**.graphql" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: kamilkisiela/graphql-inspector@v3.3.0 + with: + schema: "main:saleor/graphql/schema.graphql" diff --git a/.github/workflows/migrations-perf-test.yml b/.github/workflows/migrations-perf-test.yml new file mode 100644 index 00000000000..01782f0589c --- /dev/null +++ b/.github/workflows/migrations-perf-test.yml @@ -0,0 +1,74 @@ +name: Migrations performance test + +on: + pull_request: + types: [labeled, unlabeled, opened, closed] + +jobs: + run: + name: Run migrations performance test + if: ${{ (((github.event.action == 'labeled') && (github.event.label.name == 'migrations perf test')) || ((github.event.action == 'opened') && contains(github.event.pull_request.labels.*.name, 'migrations perf test')) && github.repository == 'saleor/saleor') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: rlespinasse/github-slug-action@e4699e49fcf890a3172a02c56ba78d867dbb9fd5 + + - name: Build and push + uses: kciter/aws-ecr-action@deed28ca73d748eba97d98847f903a3a77e702ad + with: + access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} + secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + account_id: ${{ secrets.AWS_ACCOUNT_ID }} + repo: saleor-testenvs + region: us-east-1 + tags: ${{ env.GITHUB_HEAD_REF_SLUG_URL }},${{ github.sha }} + + - name: Get pull number + run: | + echo "PULL_ID=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")" >> $GITHUB_ENV + + - name: Invoke deployment lambda + uses: gagoar/invoke-aws-lambda@d3a63ccabbed6ef817604ef6320096bde576ad40 + with: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + REGION: us-east-1 + FunctionName: migrations-perf-test-manager + Payload: >- + { + "action": "${{ github.event.action }}", + "label": "${{ env.GITHUB_HEAD_REF_SLUG_URL }}", + "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/saleor-testenvs:${{ github.sha }}", + "pr_id": "${{ env.PULL_ID }}", + "commit_hash": "${{ github.sha }}" + } + LogType: Tail + + cleanup: + name: Cleanup after migrations performance test + if: ${{ (((github.event.action == 'unlabeled') && (github.event.label.name == 'migrations perf test')) || ((github.event.action == 'closed') && contains(github.event.pull_request.labels.*.name, 'migrations perf test')) && github.repository == 'saleor/saleor') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: rlespinasse/github-slug-action@e4699e49fcf890a3172a02c56ba78d867dbb9fd5 + + - name: Get pull number + run: | + echo "PULL_ID=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")" >> $GITHUB_ENV + + - name: Invoke deployment lambda + uses: gagoar/invoke-aws-lambda@d3a63ccabbed6ef817604ef6320096bde576ad40 + with: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + REGION: us-east-1 + FunctionName: migrations-perf-test-manager + Payload: >- + { + "action": "${{ github.event.action }}", + "label": "${{ env.GITHUB_HEAD_REF_SLUG_URL }}", + "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/saleor-testenvs:${{ github.sha }}", + "pr_id": "${{ env.PULL_ID }}", + "commit_hash": "${{ github.sha }}" + } + LogType: Tail diff --git a/.github/workflows/publish-containers.rst b/.github/workflows/publish-containers.rst new file mode 100644 index 00000000000..d4b056fd030 --- /dev/null +++ b/.github/workflows/publish-containers.rst @@ -0,0 +1,43 @@ +Tagging Process +--------------- + ++-----------------------------------+-----------------------------------------------------------------------+ +| Git Ref | Container Tags | ++===================================+=======================================================================+ +| ``refs/tags/1.0.0`` | ghcr.io/saleor/saleor:1.0.0 | +| | ghcr.io/saleor/saleor:latest | ++-----------------------------------+-----------------------------------------------------------------------+ +| ``refs/tags/1.0.0a1`` | ghcr.io/saleor/saleor:1.0.0a1 | +| | ghcr.io/saleor/saleor:snapshot | ++-----------------------------------+-----------------------------------------------------------------------+ +| ``refs/tags/1.0.0rc1`` | ghcr.io/saleor/saleor:1.0.0rc1 | +| | ghcr.io/saleor/saleor:snapshot | ++-----------------------------------+-----------------------------------------------------------------------+ +| ``refs/heads/main`` | ghcr.io/saleor/saleor:unstable-main | ++-----------------------------------+-----------------------------------------------------------------------+ +| ``refs/heads/preview/my-feature`` | ghcr.io/saleor/saleor:unstable-my-feature | ++-----------------------------------+-----------------------------------------------------------------------+ + + +Version Label and Argument for Dockerfile +----------------------------------------- + +When the image is built, the following instructions will be provided to the below attached values in the dockerfile: + +.. code-block:: docker + + ARG VERSION= + LABEL org.opencontainers.image.version= + + ++-----------------------------------+--------------------------------------------------------+ +| Git Ref | Open Containers Version Value (````) | ++===================================+========================================================+ +| ``refs/tags/1.0.0`` | 1.0.0 | ++-----------------------------------+--------------------------------------------------------+ +| ``refs/tags/1.0.0a1`` | 1.0.0a1 | ++-----------------------------------+--------------------------------------------------------+ +| ``refs/heads/main`` | heads/main-0-g8ccaf9 | ++-----------------------------------+--------------------------------------------------------+ +| ``refs/heads/preview/my-feature`` | heads/preview/my-feature-0-gd12214 | ++-----------------------------------+--------------------------------------------------------+ diff --git a/.github/workflows/publish-containers.yml b/.github/workflows/publish-containers.yml new file mode 100644 index 00000000000..adfc48dc2e1 --- /dev/null +++ b/.github/workflows/publish-containers.yml @@ -0,0 +1,154 @@ +name: Publish + +on: + push: + tags: + # Matches stable and pre-releases + - "[0-9]+.[0-9]+.[0-9]+*" + branches: + - main + - ci/** + +jobs: + docker: + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + + # Outputs the name of the repository (owner/repo) + - name: Build Image Name + id: image + run: | + # The name of the owner and of the repository: owner/repository + IMAGE_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') + echo ::set-output name=image_name::${IMAGE_NAME} + + # Outputs container tags for tagged pushes starting by 'v' + # Pushes only to GitHub Container Repository (ghcr.io) + # + # Tags stable versions as :latest + # Pre-releases, alphas, etc. as :snapshot + - name: Prepare Image Tags from Git Tag + id: tagged + if: ${{ startsWith(github.ref, 'refs/tags/') }} + run: | + set -x + + # Remove everything else than the tagged version + VERSION=${GITHUB_REF#refs/tags/} + + # Tag as stable (:latest) if there is no letters in the version + # Otherwise, tag as preview (:snapshot) + if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + # Matches 1.0.0, 1.0.1, etc. + NAMED_VERSION="latest" + else + # Matches 1.0.0a1, 1.0.0rc1, etc. + NAMED_VERSION="snapshot" + fi + + TAGS=$"\ + ghcr.io/${{ steps.image.outputs.image_name }}:${NAMED_VERSION},\ + ghcr.io/${{ steps.image.outputs.image_name }}:${VERSION}\ + " + + # Output the target tags + echo " + CONTAINER_TAGS=${TAGS} + NAMED_VERSION=${NAMED_VERSION} + VERSION=${VERSION} + " >> "${GITHUB_ENV}" + + # Outputs the containers tags for staging branches + # Only publishes them onto Docker Hub + - name: Prepare Tags for Staging + id: staging + if: ${{ startsWith(github.ref, 'refs/heads/') }} + run: | + set -x + + # Version name is the branch name + # Slashes are substitued by dashes + CLEAN_BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -) + + # Target GHCR with the branch name as the tag, e.g. unstable-main + TAGS=$"\ + ghcr.io/${{ steps.image.outputs.image_name }}:unstable-${CLEAN_BRANCH_NAME} + " + + # Set version name for open-containers version label as: + # --g<6-digit-hash> + NAMED_VERSION=$(git describe --all --long | tr -d $'\n') + + # Output the target tags + echo " + CONTAINER_TAGS=${TAGS} + NAMED_VERSION=${NAMED_VERSION} + " >> "${GITHUB_ENV}" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + platforms: all + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2 + # This condition is a temporary fix until + # https://github.com/docker/buildx/issues/1044 is resolved, as it + # prevents usage of image registry. + # Due to limitation of local cache size we are skipping main branch and + # prioritize local cache for other branches e.g 3.x. + if: github.ref != 'refs/heads/main' + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ hashFiles('requirements_dev.txt') }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ secrets.CR_USERNAME }} + password: ${{ secrets.CR_PAT }} + + - name: Build and Push + id: docker_build + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.buildx.outputs.name }} + context: ./ + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ env.CONTAINER_TAGS }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + build-args: | + PROJECT_VERSION=${{ env.NAMED_VERSION }} + COMMIT_ID=${{ github.sha }} + + - name: Image digest + run: | + echo $"\ + Digest: ${{ steps.docker_build.outputs.digest }} + Tags: ${{ env.CONTAINER_TAGS }}" + + - name: Trigger staging deployments for tagged release + if: ${{ startsWith(github.ref, 'refs/tags/') }} + run: | + curl -f -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: Bearer ${{ secrets.SALEOR_RELEASE_TOKEN }}" \ + https://api.github.com/repos/saleor/saleor-multitenant/dispatches \ + -d "{\"event_type\":\"deploy-staging\",\"client_payload\":{\"version\":\"$VERSION\"}}" + + curl -f -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: Bearer ${{ secrets.SALEOR_RELEASE_TOKEN }}" \ + https://api.github.com/repos/saleor/saleor-cloud-deployments/dispatches \ + -d "{\"event_type\":\"deploy-demo-staging\",\"client_payload\":{\"version\":\"$VERSION\"}}" diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 00000000000..daf793d42ac --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,105 @@ +name: Pytest + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - "**.py" + - Dockerfile + - requirements_dev.txt + - "saleor/**" + - ".github/workflows/pytest.yml" + push: + branches: + - main + - ci/* + paths: + - "**.py" + - Dockerfile + - requirements_dev.txt + - "saleor/**" + +env: + BENCH_PATH: ./queries-results.json + DATABASE_URL: "postgres://saleor:saleor@postgres:5432/saleor" + SECRET_KEY: ci-test + +jobs: + build: + runs-on: ubuntu-latest + container: python:3.9 + + services: + postgres: + image: postgres + env: + POSTGRES_PASSWORD: saleor + POSTGRES_USER: saleor + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v3 + + - name: Install system dependencies + run: apt-get install -y libpq-dev + + - uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements_dev.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install wheel + python -m pip install -r requirements_dev.txt + + - name: Run tests + run: | + pytest \ + --cov \ + --junitxml=junit/test-results.xml \ + --django-db-bench=${{ env.BENCH_PATH }} + + - uses: actions/cache@v3 + with: + path: ~/.cache/pre-commit + key: ${{ runner.os }}-pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }} + restore-keys: | + ${{ runner.os }}-pre-commit- + + # Publish coverage and test results + - uses: codecov/codecov-action@v2 + + - uses: actions/upload-artifact@v3 + with: + name: pytest-results + path: junit/test-results.xml + if: ${{ always() }} + + # Publish detected differences as comment + - uses: NyanKiyoshi/pytest-django-queries-ci-tools@v1 + with: + query_raw_dump_path: ${{ env.BENCH_PATH }} + diff_endpoint: "https://dtab784j47g1o.cloudfront.net/default/saleor-db-queries-bot-diff" + diff_results_base_url: "https://dtab784j47g1o.cloudfront.net" + if: github.event_name == 'pull_request' && github.repository == 'saleor/saleor' + + # Save results for future comparison against pull requests + - uses: NyanKiyoshi/pytest-django-queries-ci-tools@v1 + with: + query_raw_dump_path: ${{ env.BENCH_PATH }} + upload_endpoint: ${{ secrets.QUERIES_UPLOAD_ENDPOINT_URL }} + upload_secret_key: ${{ secrets.QUERIES_UPLOAD_SECRET }} + if: github.event_name == 'push' && github.repository == 'saleor/saleor' + + # Run linters and Django related checks + - name: Run Linters and Checks + run: | + pre-commit run --all + if: ${{ always() }} diff --git a/.github/workflows/test-env-cleanup.yml b/.github/workflows/test-env-cleanup.yml new file mode 100644 index 00000000000..2b72fc6f053 --- /dev/null +++ b/.github/workflows/test-env-cleanup.yml @@ -0,0 +1,37 @@ +name: TEST-ENV-CLEANUP +# Build and deploy test instance for every pull request + +on: + pull_request: + types: [closed, unlabeled] + branches: ["**"] + +jobs: + cleanup: + name: Remove test environment deployment + if: ${{ ((github.event.action == 'unlabeled') && (github.event.label.name == 'test deployment')) || ((github.event.action == 'closed') && contains(github.event.pull_request.labels.*.name, 'test deployment')) }} + runs-on: ubuntu-latest + steps: + - uses: rlespinasse/github-slug-action@3.1.0 + + - name: Invoke deployment lambda + uses: gagoar/invoke-aws-lambda@v3.3.0 + with: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + REGION: us-east-1 + FunctionName: test-env-manager + Payload: >- + { + "action": "${{ github.event.action }}", + "label": "${{ env.GITHUB_HEAD_REF_SLUG_URL }}", + "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/saleor-testenvs:${{ env.GITHUB_HEAD_REF_SLUG_URL }}" + } + LogType: Tail + + - name: Mark deployment as deactivated + uses: bobheadxi/deployments@v0.4.2 + with: + step: deactivate-env + token: ${{ secrets.GITHUB_TOKEN }} + env: ${{ env.GITHUB_HEAD_REF_SLUG_URL }} diff --git a/.github/workflows/test-env-deploy.yml b/.github/workflows/test-env-deploy.yml new file mode 100644 index 00000000000..7abb5330d4f --- /dev/null +++ b/.github/workflows/test-env-deploy.yml @@ -0,0 +1,66 @@ +name: TEST-ENV-DEPLOYMENT +# Build and deploy test instance for every pull request + +on: + pull_request: + types: [reopened, synchronize, labeled] + branches: ["**"] + +jobs: + deploy: + name: Deploy test environment for labeled pull requests + if: ${{ ((github.event.action == 'labeled') && (github.event.label.name == 'test deployment')) || ((github.event.action != 'labeled') && contains(github.event.pull_request.labels.*.name, 'test deployment')) }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: rlespinasse/github-slug-action@3.1.0 + + - name: Set domain + id: set-domain + # Set test instance domain based on branch name slug + run: | + echo "::set-output name=domain::${{ env.GITHUB_HEAD_REF_SLUG_URL }}.api.saleor.rocks" + + - name: Start deployment + uses: bobheadxi/deployments@v0.4.2 + id: deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: ${{ env.GITHUB_HEAD_REF_SLUG_URL }} + ref: ${{ github.head_ref }} + + - name: Build and push + uses: kciter/aws-ecr-action@v1 + with: + access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} + secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + account_id: ${{ secrets.AWS_ACCOUNT_ID }} + repo: saleor-testenvs + region: us-east-1 + tags: ${{ env.GITHUB_HEAD_REF_SLUG_URL }},${{ github.sha }} + + - name: Invoke deployment lambda + uses: gagoar/invoke-aws-lambda@v3.3.0 + with: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + REGION: us-east-1 + FunctionName: test-env-manager + Payload: >- + { + "action": "${{ github.event.action }}", + "label": "${{ env.GITHUB_HEAD_REF_SLUG_URL }}", + "image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com/saleor-testenvs:${{ github.sha }}" + } + LogType: Tail + + - name: Update deployment status + uses: bobheadxi/deployments@v0.4.2 + if: always() + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + env_url: https://${{ steps.set-domain.outputs.domain }}/graphql/ + deployment_id: ${{ steps.deployment.outputs.deployment_id }} diff --git a/.github/workflows/test-migrations-compatibility.yml b/.github/workflows/test-migrations-compatibility.yml new file mode 100644 index 00000000000..6520a240bd4 --- /dev/null +++ b/.github/workflows/test-migrations-compatibility.yml @@ -0,0 +1,65 @@ +name: Test migrations compatibility + +on: + pull_request: + branches: + - "3.*" + - "main" + paths: + - "**/migrations/**" + +env: + DATABASE_URL: "postgres://saleor:saleor@postgres:5432/saleor" + SECRET_KEY: ci-test + +jobs: + build: + runs-on: ubuntu-latest + container: python:3.9 + + services: + postgres: + image: postgres + env: + POSTGRES_PASSWORD: saleor + POSTGRES_USER: saleor + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout branch + uses: actions/checkout@v3 + + - name: Install system dependencies + run: apt-get install -y libpq-dev + + - name: Cache pip + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements_dev.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install wheel + python -m pip install -r requirements_dev.txt + + - name: Migrate + run: | + export DJANGO_SETTINGS_MODULE=saleor.tests.settings + ./manage.py migrate + + - name: Checkout base + uses: actions/checkout@v3 + with: + ref: ${{ github['base_ref'] }} + + - name: Run tests + run: | + export PYTEST_DB_URL=$DATABASE_URL + pytest -n 0 --reuse-db diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000000..1057044e4c9 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,8 @@ +inherit_from: .rubocop_todo.yml + +require: + - rubocop-rails + - rubocop-performance + +AllCops: + NewCops: enable diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000000..8c9c1626058 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,194 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2022-05-14 11:51:55 UTC using RuboCop version 1.23.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +Bundler/OrderedGems: + Exclude: + # - 'Gemfile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: with_first_argument, with_fixed_indentation +Layout/ArgumentAlignment: + Exclude: + - "config/initializers/cors.rb" + +# Offense count: 6 +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Exclude: + - "bin/bundle" + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/EmptyLines: + Exclude: + - "config/environments/development.rb" + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Exclude: + # - 'app/controllers/api/v1/api_controller.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. +Layout/ExtraSpacing: + Exclude: + - "config/environments/production.rb" + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented +Layout/MultilineOperationIndentation: + Exclude: + - "bin/bundle" + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. +# SupportedStylesForExponentOperator: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - "config/environments/production.rb" + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBrackets: space, no_space +Layout/SpaceInsideArrayLiteralBrackets: + Exclude: + - "config/environments/production.rb" + +# Offense count: 1 +# Configuration parameters: IgnoredMethods. +Metrics/CyclomaticComplexity: + Max: 9 + +# Offense count: 1 +# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. +Metrics/MethodLength: + Max: 21 + +# Offense count: 1 +# Configuration parameters: IgnoredMethods. +Metrics/PerceivedComplexity: + Max: 9 + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Enabled: false + # Exclude: + # - 'app/controllers/api/v1/api_controller.rb' + # - 'test/channels/application_cable/connection_test.rb' + # - 'test/test_helper.rb' + +# Offense count: 2 +# Configuration parameters: AllowedConstants. +Style/Documentation: + Enabled: false + # Exclude: + # - 'spec/**/*' + # - 'test/**/*' + # - 'app/models/application_record.rb' + # - 'config/application.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/ExpandPathArguments: + Exclude: + - "bin/bundle" + +# Offense count: 33 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Style/GlobalStdStream: + Exclude: + - "config/environments/production.rb" + +# Offense count: 2 +# Cop supports --auto-correct. +Style/IfUnlessModifier: + Exclude: + - "bin/bundle" + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - "config/initializers/cors.rb" + +# Offense count: 1 +# Cop supports --auto-correct. +Style/PerlBackrefs: + Exclude: + - "bin/bundle" + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: SafeForConstants. +Style/RedundantFetchBlock: + Exclude: + - "config/puma.rb" + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: RequireEnglish. +# SupportedStyles: use_perl_names, use_english_names +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names + +# Offense count: 89 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Enabled: true + Exclude: + - "config/**/*" + - "test/**/*" + - "config.ru" + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: . +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: percent + MinSize: 10 + +Rails/FilePath: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 360 + +Naming/VariableNumber: + Enabled: false + +Rails/SkipsModelValidations: + Enabled: false diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..d0f74a77643 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "charliermarsh.ruff", + "editorconfig.editorconfig", + "github.vscode-pull-request-github", + "ms-python.black-formatter", + "ms-python.pylint", + "ms-python.python", + "ms-python.vscode-pylance", + "streetsidesoftware.code-spell-checker" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..2fb2f98b576 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.formatting.provider": "black", + "python.languageServer": "Pylance", + "python.linting.mypyEnabled": true, + "python.analysis.typeCheckingMode": "basic" +} diff --git a/LICENSE b/LICENSE index e69de29bb2d..64795f9cc56 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,30 @@ +BSD 3-Clause License + +Copyright (c) 2020-2022, Maearon Commerce +Copyright (c) 2010-2020, Maearon Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/controllers/api/concerns/.keep b/app/controllers/api/concerns/.keep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/app/controllers/api/concerns/errors_handler.rb b/app/controllers/api/concerns/errors_handler.rb deleted file mode 100644 index cbe37282d9b..00000000000 --- a/app/controllers/api/concerns/errors_handler.rb +++ /dev/null @@ -1,60 +0,0 @@ -module ErrorsHandler - extend ActiveSupport::Concern - - included do - unless Rails.env.development? - rescue_from StandardError, with: :rescue500 - rescue_from ActionController::RoutingError, with: :rescue404 - rescue_from ActiveRecord::RecordNotFound, with: :rescue404 - end - rescue_from JWT::DecodeError, with: :rescue400 - rescue_from JWT::InvalidAudError, with: :rescue401 - rescue_from JWT::InvalidIssuerError, with: :rescue401 - rescue_from JWT::InvalidSubError, with: :rescue401 - rescue_from JWT::ExpiredSignature, with: :rescue401 - end - - private - - def rescue400(exception = nil) - log_message = '400 Bad Request' - log_message << " exception: #{exception.message}" if exception - logger.warn log_message - response400 - end - - def rescue401(exception = nil) - log_message = '401 Unauthorized' - log_message << " exception: #{exception.message}" if exception - logger.warn log_message - response401 - end - - def rescue403(exception = nil) - log_message = '403 Forbidden' - log_message << " exception: #{exception.message}" if exception - logger.warn log_message - response403 - end - - def rescue404(exception = nil) - log_message = '404 Not Found' - log_message << " exception: #{exception.message}" if exception - logger.warn log_message - response404 - end - - def rescue500(exception = nil) - log_message = '500 Internal Server Error' - log_message << " exception: #{exception.message} #{exception.backtrace.inspect}" if exception - logger.error log_message - response500 - end - - def rescue503(exception = nil) - log_message = '503 Service Unavailable' - log_message << " exception: #{exception.message} #{exception.backtrace.inspect}" if exception - logger.error log_message - response503 - end -end diff --git a/app/controllers/api/concerns/responses_handler.rb b/app/controllers/api/concerns/responses_handler.rb deleted file mode 100644 index 427387fb8d1..00000000000 --- a/app/controllers/api/concerns/responses_handler.rb +++ /dev/null @@ -1,74 +0,0 @@ -module ResponsesHandler - private - - def response200(class_name = controller_name, method_name = action_name, option_data: {}) - base_body = { status: 200, message: "OK #{class_name.classify} #{method_name.classify}" } - render status: :ok, json: base_body.merge(option_data) - end - - def response201(class_name = controller_name, option_data: {}) - base_body = { status: 201, message: "Created #{class_name.classify}" } - render status: :created, json: base_body.merge(option_data) - end - - def response400(option_data: {}) - base_body = { status: 400, message: 'Bad Request' } - render status: :bad_request, json: base_body.merge(option_data) - end - - def response401(option_data: {}) - base_body = { status: 401, message: 'Unauthorized' } - render status: :unauthorized, json: base_body.merge(option_data) - end - - def response403(option_data: {}) - base_body = { status: 403, message: 'Forbidden' } - render status: :forbidden, json: base_body.merge(option_data) - end - - def response404(class_name = nil, option_data: {}) - class_message = class_name.present? ? "#{class_name.classify} " : '' - base_body = { status: 404, message: "#{class_message}Not Found" } - render status: :not_found, json: base_body.merge(option_data) - end - - def response422(option_data: {}) - base_body = { status: 422, message: 'Unprocessable Entity' } - render status: :unprocessable_entity, json: base_body.merge(option_data) - end - - def response426(option_data: {}) - base_body = { status: 426, message: 'Upgrade Required' } - render status: :upgrade_required, json: base_body.merge(option_data) - end - - def response500(option_data: {}) - base_body = { status: 500, message: 'Internal Server Error' } - render status: :internal_server_error, json: base_body.merge(option_data) - end - - def response503(option_data: {}) - base_body = { status: 503, message: 'Service Unavailable' } - render status: :service_unavailable, json: base_body.merge(option_data) - end - - def response401_with_error(message) - response401(option_data: { errors: message }) - end - - def response403_with_error(message) - response403(option_data: { errors: message }) - end - - def response404_with_error(message, class_name = nil) - response404(class_name, option_data: { errors: message }) - end - - def response422_with_error(messages) - response422(option_data: { errors: messages }) - end - - def response426_with_error(message) - response426(option_data: { errors: message }) - end -end diff --git a/app/controllers/api/sessions_controller.rb b/app/controllers/api/sessions_controller.rb index b74ad3432b5..35f6e8d9868 100644 --- a/app/controllers/api/sessions_controller.rb +++ b/app/controllers/api/sessions_controller.rb @@ -2,6 +2,9 @@ class Api::SessionsController < Api::ApiController before_action :authenticate!, except: %i[create] def index + # binding.b + # sudo docker ps + # sudo docker attach 32b385027bd8 @current_user = current_user if current_user end diff --git a/app/helpers/api_sessions_helper.rb b/app/helpers/api_sessions_helper.rb deleted file mode 100644 index 6abd4cbcc13..00000000000 --- a/app/helpers/api_sessions_helper.rb +++ /dev/null @@ -1,85 +0,0 @@ -module ApiSessionsHelper - - # Logs in the given user. - def log_in(user) - session[:user_id] = user.id - end - - # Remembers a user in a persistent session. - # def remember(user) - # user.remember - # cookies.permanent.encrypted[:user_id] = user.id - # cookies.permanent[:remember_token] = user.remember_token - # end - - # Returns the user corresponding to the remember token cookie. - def current_user - # if (user_id = session[:user_id]) - # @current_user ||= User.find_by(id: user_id) - # elsif (user_id = cookies.encrypted[:user_id]) - decoded_hash = decoded_token - if !decoded_hash.empty? - puts decoded_hash.class - user_id = decoded_hash[0]['user_id'] - log_in user - @current_user = User.find_by(id: user_id) - # if user && user.authenticated?(:remember, auth_header.split(' ')[2]) - # log_in user - # @current_user = user - # end - else - nil - end - # end - end - - # Returns true if the given user is the current user. - def current_user?(user) - user == current_user - end - - # Returns true if the user is logged in, false otherwise. - def logged_in? - !current_user.nil? - end - - # Forgets a persistent session. - # def forget(user) - # user.forget - # cookies.delete(:user_id) - # cookies.delete(:remember_token) - # end - - # Logs out the current user. - def log_out - forget(current_user) - session.delete(:user_id) - @current_user = nil - end - - # Redirects to stored location (or to the default). - # def redirect_back_or(default) - # redirect_to(session[:forwarding_url] || default) - # session.delete(:forwarding_url) - # end - - # Stores the URL trying to be accessed. - # def store_location - # session[:forwarding_url] = request.original_url if request.get? - # end - - def encode_token(payload) - JWT.encode(payload, 'my_secret') - end - - def decoded_token - if auth_header - token = auth_header.split(' ')[1] - begin - JWT.decode(token, 'my_secret', true, algorithm: 'HS256') - rescue JWT::DecodeError - [] - end - end - end -end diff --git a/app/services/jwt/user/decode_token_service.rb b/app/services/jwt/user/decode_token_service.rb index cb7d327fca0..a48a7de4163 100644 --- a/app/services/jwt/user/decode_token_service.rb +++ b/app/services/jwt/user/decode_token_service.rb @@ -15,7 +15,7 @@ def call attr_reader :auth_header def id_from_claim - decoded_token[0].fetch('rails_boilerplate_user_claim').fetch('id') if decoded_token + decoded_token[0].fetch('sub') if decoded_token end def decoded_token @@ -32,9 +32,9 @@ def decoded_token def jwt_claims { - iss: ISS, verify_iss: true, - sub: SUB, verify_sub: true, - aud: AUD, verify_aud: true, + # iss: ISS, verify_iss: true, + # sub: SUB, verify_sub: true, + # aud: AUD, verify_aud: true, algorithm: ALGORITHM } end diff --git a/app/services/jwt/user/encode_token_service.rb b/app/services/jwt/user/encode_token_service.rb index cb43dbfa576..f8c25317f87 100644 --- a/app/services/jwt/user/encode_token_service.rb +++ b/app/services/jwt/user/encode_token_service.rb @@ -31,7 +31,7 @@ def call def encode_token(type) payload = jwt_claims.merge(user_claims, {type: type}) - JWT.encode(payload, Rails.application.credentials.secret_key_base, ALGORITHM, { typ: 'JWT' }) # ALGORITHM = HS256 + JWT.encode(payload, Rails.application.credentials[:secret_key_base], ALGORITHM, { typ: 'JWT' }) # ALGORITHM = HS256 end def jwt_claims diff --git a/app/views/api/sessions/create.json.jbuilder b/app/views/api/sessions/create.json.jbuilder index 418f837caae..ea91f9ef4cb 100644 --- a/app/views/api/sessions/create.json.jbuilder +++ b/app/views/api/sessions/create.json.jbuilder @@ -1,3 +1,6 @@ +json.status 'ok' +json.type 'account' +json.currentAuthority @user.admin json.user do json.extract! @user, :id, :email, :name json.role @user.admin @@ -7,10 +10,8 @@ json.tokens do json.token @user.token json.expires @user.token_expiration_at end -end -json.refresh do - json.access do - json.token @user.refresh_token - json.expires @user.refresh_token_expiration_at + json.refresh do + json.token @user.token + json.expires @user.token_expiration_at end end diff --git a/app/views/api/sessions/index.json.jbuilder b/app/views/api/sessions/index.json.jbuilder index d0adcbd97d7..0271870e72f 100644 --- a/app/views/api/sessions/index.json.jbuilder +++ b/app/views/api/sessions/index.json.jbuilder @@ -1 +1,50 @@ -json.extract! @current_user, :id, :name, :email, :admin if @current_user +if @current_user then +json.name @current_user.name +json.avatar "https://secure.gravatar.com/avatar/#{Digest::MD5::hexdigest(@current_user.email.downcase)}?s=50" +json.userid @current_user.id +json.email @current_user.email +json.signature 'Be tolerant to diversity, tolerance is a virtue' +json.title 'Interaction expert' +json.group 'Ant Financial - XX Business Group - XX Platform Department - XX Technology Department - UED' +json.tags [ + { + key: '0', + label: 'Very thoughtful', + }, + { + key: '1', + label: 'Focus on design', + }, + { + key: "2'Hot~", + }, + { + key: '3', + label: 'Long legs', + }, + { + key: '4', + label: 'C change girl', + }, + { + key: '5', + label: 'All rivers are inclusive', + }, +] +json.notifyCount 12 +json.unreadCount 11 +json.country 'Vietnam' +json.access 'admin' +json.geographic do + json.province do + json.label 'Zhejiang Province' + json.key '330000' + end + json.city do + json.label 'Hangzhou' + json.key '330100' + end +end +json.address 'No. 77 Gongzhuan Road, Xihu District' +json.phone '0912-915132888' +end diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index 7d2969c11f3..46b20b361c7 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -P/C8dFRxjFXRfytGWNAzWvet7gl9kE7N2qLntKBM61r6l51nWzW/jzsZerptdhU1POKZjiUj2z+Pc8rNbykJdzMOh8LLCkioLazt5giZ8C7kTLVvfYO5v0+CsRf8GS4WvSHzFVbZjvgjfga0urm+VyhCSJXodguGcQO410FlaGDrJuU4oAI9Yfev1+qUIa6KqH/AEac2jNbQs84WqXK5mgNWpJK72rzchjjDW6jL1YGCi2hGWCBh8D9zofY6fIeCWHFyEu5Z8HB3DlkuE0ociQCrYhysNseu6ZPbL/j5fuJqH4fFWcqQw5ETgmX2ZuJptChuAA7t5ci+TqrfPGTd8L8RUZ97lydy5vB12qR6h0VTv9lQtYgXKj6rdoanQL99hO9g5DjnSZ3Vc/QlKiBByi2hkPZG5d/cfB0c--Mms468mpk5/zcpbc--aQdP8gsSeFzk0I2T6TrAgw== +GIcD9er9OSNowbqny0GAXPm6jrOzZpVJLi1ifJGPavzOOacZB1REyHw2aQM9a8p+0IBZ5UG2GLUxPR63hHUTStVfPm6HjWIPOTDUZbftbLpyvFKYy6GZvPZWplSwafFG3ynexLYFEsRL84MA8smZ3wOs3xuz4AnjbfRS/ProO4/w1q39QwMfKl+m+v+PzadfAaYIBme64ark2sUNaEWF0VVTOjpozFbg3dDvCDdie2tTVBSTmfc60u7wGCK8f9GVVA38oWcvqtBBlYfHT6/E+L2LCV/uMZoa2RUyB8gtHQCjnBztjYRzBmZz4LUr7NwHlli3YAR9Zde3JYeY0zaiJP8+UbnPD8ksVEih/iLLVl9iOEJM93Uupsls4rJow577k0otYGO3oxqVEyosjrOVXjELsQGgPPZXRKkI--rW/suZGVryiH+QD9--majOqq701KkzCYfDkw2ldA== \ No newline at end of file diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb index e56b5096e2b..4a9d85114d6 100644 --- a/config/initializers/cors.rb +++ b/config/initializers/cors.rb @@ -37,6 +37,14 @@ headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true end + + allow do + origins 'http://localhost:8000' + + resource '*', + headers: :any, + methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true + end allow do origins 'http://localhost:8080' diff --git a/editor.swagger.io.yaml b/editor.swagger.io.yaml new file mode 100644 index 00000000000..edd5fed61f3 --- /dev/null +++ b/editor.swagger.io.yaml @@ -0,0 +1,626 @@ +openapi: 3.0.0 +info: + description: Routes + version: 1.0.0 + title: Rails Boilerplate + contact: + email: from@example.com + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' +servers: + # Added by API Auto Mocking Plugin + - description: SwaggerHub API Auto Mocking + url: https://virtserver.swaggerhub.com/nickeryno/Rails Boilerplate/1.0.0 +tags: + - name: Auth + description: Authentication + - name: Users + description: User management and retrieval + - name: Questions + description: Question management and retrieval +paths: + /auth/register: + post: + summary: Register as user + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - email + - password + properties: + name: + type: string + email: + type: string + format: email + description: must be unique + password: + type: string + format: password + minLength: 8 + description: At least one number and one letter + example: + name: fake name + email: fake@example.com + password: password1 + responses: + '201': + description: Created + content: + application/json: + schema: + type: object + properties: + user: + $ref: '#/components/schemas/User' + tokens: + $ref: '#/components/schemas/AuthTokens' + '400': + $ref: '#/components/responses/DuplicateEmail' + /auth/login: + post: + summary: Login + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + - password + properties: + email: + type: string + format: email + password: + type: string + format: password + example: + email: fake@example.com + password: password1 + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + user: + $ref: '#/components/schemas/User' + tokens: + $ref: '#/components/schemas/AuthTokens' + '401': + description: Invalid email or password + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 401 + message': Invalid email or password + /auth/logout: + post: + summary: Logout, + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - refreshToken + properties: + refreshToken: + type: string + example: + refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZWJhYzUzNDk1NGI1NDEzOTgwNmMxMTIiLCJpYXQiOjE1ODkyOTg0ODQsImV4cCI6MTU4OTMwMDI4NH0.m1U63blB0MLej_WfB7yC2FTMnCziif9X8yzwDEfJXAg + responses: + '204': + description: No content + '404': + $ref: '#/components/responses/NotFound' + /auth/refresh-tokens: + post: + summary: Refresh auth tokens + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - refreshToken + properties: + refreshToken: + type: string + example: + refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZWJhYzUzNDk1NGI1NDEzOTgwNmMxMTIiLCJpYXQiOjE1ODkyOTg0ODQsImV4cCI6MTU4OTMwMDI4NH0.m1U63blB0MLej_WfB7yC2FTMnCziif9X8yzwDEfJXAg + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/AuthTokens' + '401': + $ref: '#/components/responses/Unauthorized' + /auth/forgot-password: + post: + summary: Forgot password + description: An email will be sent to reset password. + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - email + properties: + email: + type: string + format: email + example: + email: fake@example.com' + responses: + '204': + description: No content' + '404': + $ref: '#/components/responses/NotFound' + /auth/reset-password: + post: + summary: Reset password + tags: + - Auth + parameters: + - in: query + name: token, + required: true + schema: + type: string + description: The reset password token' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - password + properties: + password: + type: string + format: password + minLength: 8 + description: At least one number and one letter + example: + password: password1 + responses: + '204': + description: No content + '401': + description: Password reset failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 401 + message': Password reset failed' + /auth/send-verification-email: + post: + summary: Send verification email + description: An email will be sent to verify email. + tags: + - Auth + security: + - bearerAuth: [] + responses: + '204': + description: No content' + '401': + $ref: '#/components/responses/Unauthorized' + /auth/verify-email: + post: + summary: verify email + tags: + - Auth + parameters: + - in: query + name: token, + required: true + schema: + type: string + description: The verify email token' + responses: + '204': + description: No content' + '401': + description: verify email failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 401 + message': verify email failed' + /users: + post: + summary: Create a user + description: Only admins can create other users. + tags: + - Users + security: + - bearerAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - name + - email + - password + - role + properties: + name: + type: string + email: + type: string + format: email + description: must be unique + password: + type: string + format: password + minLength: 8 + description: At least one number and one letter + role: + type: string + enum: + - user + - admin + example: + name: fake name + email: fake@example.com + password: password1 + role: user + responses: + '201': + description: Created, + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/DuplicateEmail' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + get: + summary: Get all users + description: Only admins can retrieve all users. + tags: + - Users + security: + - bearerAuth: [] + parameters: + - in: query + name: name + schema: + type: string + description: User name + - in: query + name: role + schema: + type: string + description: User role + - in: query + name: sortBy + schema: + type: string + description: sort by query in the form of field:desc/asc (ex. name:asc) + - in: query + name: limit + schema: + type: integer + minimum: 1 + default: 10 + description: Maximum number of users + - in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: Page number + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + $ref: '#/components/schemas/User' + page: + type: integer + example: 1 + limit: + type: integer + example: 10 + totalPages: + type: integer + example: 1 + totalResults: + type: integer + example: 1 + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /users/{id}: + get: + summary: Get a user + description: Logged in users can fetch only their own user information. Only admins can fetch other users. + tags: + - Users + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: User id + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + patch: + summary: Update a user + description: Logged in users can only update their own information. Only admins can update other users. + tags: + - Users + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: User id + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + email: + type: string + format: email + description: must be unique + password: + type: string + format: password + minLength: 8 + description: At least one number and one letter + example: + name: fake name + email: fake@example.com + password: password1 + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + $ref: '#/components/responses/DuplicateEmail' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + delete: + summary: Delete a user + description: Logged in users can delete only themselves. Only admins can delete other users. + tags: + - Users + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: User id + responses: + '200': + description: No content + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' + /questions/{id}: + get: + summary: Get a question + description: Logged in users can fetch only their own questions information. Only admins can fetch other questions. + tags: + - Questions + security: + - bearerAuth: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + description: Question id + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Question' + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' +components: + schemas: + User: + type: object + properties: + id: + type: string + email: + type: string + format: email + name: + type: string + role: + type: string + enum: + - user + - admin + example: + id: 5ebac534954b54139806c112, + email: fake@example.com + name: fake name + role: user + Token: + type: object + properties: + Token: + type: string + expires: + type: string + format: date-time + example: + token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZWJhYzUzNDk1NGI1NDEzOTgwNmMxMTIiLCJpYXQiOjE1ODkyOTg0ODQsImV4cCI6MTU4OTMwMDI4NH0.m1U63blB0MLej_WfB7yC2FTMnCziif9X8yzwDEfJXAg, + expires: 2020-05-12T16:18:04.793Z' + AuthTokens: + type: object + properties: + access: + $ref: '#/components/schemas/Token' + refresh: + $ref: '#/components/schemas/Token' + Error: + type: object + properties: + code: + type: number + message: + type: string + Question: + type: object + required: + - text + properties: + text: + type: string + example: 'Which language is used for web apps?' + manufacturer: + $ref: '#/components/schemas/Answer' + Answer: + required: + - text + properties: + text: + type: string + example: 'Python' + flag: + type: boolean + example: 'true' + phone: + type: string + example: 408-867-5309 + type: object + responses: + DuplicateEmail: + description: Email already taken, + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 400, + message': Email already taken' + Unauthorized: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 401 + message': Please authenticate + Forbidden: + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 403, + message': Forbidden + NotFound: + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + example: + code: 404 + message': Not found' + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT diff --git a/maearon.talentapi_collection.json b/maearon.talentapi_collection.json new file mode 100644 index 00000000000..940020268c6 --- /dev/null +++ b/maearon.talentapi_collection.json @@ -0,0 +1,598 @@ +{ + "version": 6, + "entities": [ + { + "entity": { + "type": "Project", + "description": "https://app.swaggerhub.com/apis-docs/Kakeishindan/Manenoba/1.0.0", + "id": "97e49ed9-b053-4390-84c6-57e4fd2e4bfc", + "name": "maearon" + }, + "children": [ + { + "entity": { + "type": "Service", + "id": "65e94e87-67ba-4d69-8606-9dd267919a3e", + "name": "auth" + }, + "children": [ + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"email\": \"example@gamil.com\"\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/auth/forgot-password" + }, + "id": "aaba4466-199b-487f-b8ef-6ac2015078e1", + "name": "forgot password - failure", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0Iiwic3ViIjoibWFuZW5vYmFiYWNrLXVzZXIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdCJdLCJleHAiOjE2NjMwNTI4OTQsImlhdCI6MTY2Mjk2NjQ5NCwibWFuZW5vYmFiYWNrX3VzZXJfY2xhaW0iOnsiaWQiOjExfX0.mgQbjSb_s67iszXX6S4l67v6zXZBAg-kc3rtyl2H_5U" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.1", + "name": "GET" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{ \n \"auth\": {\n \t\"email\": \"example@gmail.com\",\n \t\"password\": \"Abc@12345678\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/sessions" + }, + "id": "3025b13d-ce46-44ea-92e5-cdfb31f0d45f", + "name": "get session", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer ${token}" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"auth\": {\n \"email\": \"example@railstutorial.org\",\n \"password\": \"foobar\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/login" + }, + "id": "e96b01bc-0cbf-432e-a284-6ba87faa744a", + "name": "login", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/json" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZWJhYzUzNDk1NGI1NDEzOTgwNmMxMTIiLCJpYXQiOjE1ODkyOTg0ODQsImV4cCI6MTU4OTMwMDI4NH0.m1U63blB0MLej_WfB7yC2FTMnCziif9X8yzwDEfJXAg\"\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/auth/revoke" + }, + "id": "87704aa0-70d2-497b-a9c0-3547d55e994c", + "name": "logout - failure", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0Iiwic3ViIjoibWFuZW5vYmFiYWNrLXVzZXIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdCJdLCJleHAiOjE2NjMwNTI4OTQsImlhdCI6MTY2Mjk2NjQ5NCwibWFuZW5vYmFiYWNrX3VzZXJfY2xhaW0iOnsiaWQiOjExfX0.mgQbjSb_s67iszXX6S4l67v6zXZBAg-kc3rtyl2H_5U" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1ZWJhYzUzNDk1NGI1NDEzOTgwNmMxMTIiLCJpYXQiOjE1ODkyOTg0ODQsImV4cCI6MTU4OTMwMDI4NH0.m1U63blB0MLej_WfB7yC2FTMnCziif9X8yzwDEfJXAg\"\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/auth/refresh-tokens" + }, + "id": "69ad3e28-421c-422e-96f6-818f2ee5dc3d", + "name": "refresh auth tokens - failure", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0Iiwic3ViIjoibWFuZW5vYmFiYWNrLXVzZXIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdCJdLCJleHAiOjE2NjMwNTI4OTQsImlhdCI6MTY2Mjk2NjQ5NCwibWFuZW5vYmFiYWNrX3VzZXJfY2xhaW0iOnsiaWQiOjExfX0.mgQbjSb_s67iszXX6S4l67v6zXZBAg-kc3rtyl2H_5U" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"user\": {\n \t\"name\": \"Korgiwannafly Dev\",\n \"email\": \"korgiwannafly-dev@gmail.com\",\n \"password\": \"Aa123456789@*\",\n \"password_confirmation\": \"Aa123456789@*\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users" + }, + "id": "8d8b10b5-5fbb-4d08-956d-ba77d93cd273", + "name": "register", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/json" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"password\": \"Abc@12345678\"\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/auth/reset-password" + }, + "id": "d289b9c5-f4f1-48ec-83ad-3326bbd883ec", + "name": "reset password - failure", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0Iiwic3ViIjoibWFuZW5vYmFiYWNrLXVzZXIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdCJdLCJleHAiOjE2NjMwNTI4OTQsImlhdCI6MTY2Mjk2NjQ5NCwibWFuZW5vYmFiYWNrX3VzZXJfY2xhaW0iOnsiaWQiOjExfX0.mgQbjSb_s67iszXX6S4l67v6zXZBAg-kc3rtyl2H_5U" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.3", + "name": "POST" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{ \n \"send_verification_email\": {\n \t\"email\": \"manhnd@reactplus.jp\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users/send-verification-email" + }, + "id": "d761f3cd-239d-4356-ae0a-9c8f5763809e", + "name": "send_verification_email", + "headers": [ + { + "enabled": true, + "name": "Content-Type", + "value": "application/json" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.1", + "name": "GET" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [ + { + "enabled": true, + "name": "email", + "value": "manhnd@reactplus.jp" + }, + { + "enabled": true, + "name": "locale", + "value": "ja" + } + ] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/account_activations/10/edit" + }, + "id": "3e6b3b81-e8b8-41dd-8855-6dde49a97e46", + "name": "verify email - failure", + "headers": [ + { + "enabled": true, + "name": "token", + "value": "sadsad" + }, + { + "enabled": true, + "name": "email", + "value": "example@gmail.com" + } + ] + } + } + ] + }, + { + "entity": { + "type": "Service", + "id": "2229c6a0-3431-4bb8-a478-3eb29b570560", + "name": "user" + }, + "children": [ + { + "entity": { + "type": "Request", + "method": { + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.5", + "name": "DELETE" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"name\": \"fake name\",\n \"email\": \"fake@example.com\",\n \"password\": \"password1\"\n}\n" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users/2" + }, + "id": "46e4ffdc-7d9a-49ed-a002-854aba8e19a9", + "name": "delete a user", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer ${token}" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.1", + "name": "GET" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{ \n \"auth\": {\n \t\"email\": \"example@gmail.com\",\n \t\"password\": \"Abc@12345678\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users" + }, + "id": "38f3949d-4574-4ce8-b563-3f45ad12a6db", + "name": "get all users", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer ${token}" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "link": "http://tools.ietf.org/html/rfc7231#section-4.3.1", + "name": "GET" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{ \n \"auth\": {\n \t\"email\": \"example@gmail.com\",\n \t\"password\": \"Abc@12345678\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users/${id}" + }, + "id": "6b6dde32-2ba5-44f3-a3ee-1b5d106aebc7", + "name": "get user", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0Iiwic3ViIjoibWFuZW5vYmFiYWNrLXVzZXIiLCJhdWQiOlsiaHR0cDovL2xvY2FsaG9zdCJdLCJleHAiOjE2NjMwNTI4OTQsImlhdCI6MTY2Mjk2NjQ5NCwibWFuZW5vYmFiYWNrX3VzZXJfY2xhaW0iOnsiaWQiOjExfX0.mgQbjSb_s67iszXX6S4l67v6zXZBAg-kc3rtyl2H_5U" + } + ] + } + }, + { + "entity": { + "type": "Request", + "method": { + "requestBody": true, + "link": "http://tools.ietf.org/html/rfc5789", + "name": "PATCH" + }, + "body": { + "formBody": { + "overrideContentType": true, + "encoding": "application/x-www-form-urlencoded", + "items": [] + }, + "bodyType": "Text", + "textBody": "{\n \"user\": {\n \"name\": \"Mark Mowatt\",\n \"email\": \"manhng132@gmail.com\",\n \"password\": \"Aa123456789@*\",\n \"password_confirmation\": \"Aa123456789@*\"\n }\n}" + }, + "uri": { + "query": { + "delimiter": "&", + "items": [] + }, + "scheme": { + "name": "http", + "version": "V11" + }, + "host": "localhost:3000", + "path": "/api/v1/users/${id}" + }, + "id": "59720def-8c11-49d5-a0f9-fa20626787a0", + "name": "update a user", + "headers": [ + { + "enabled": true, + "name": "Authorization", + "value": "Bearer ${token}" + }, + { + "enabled": true, + "name": "Content-Type", + "value": "application/json" + } + ] + } + } + ] + } + ] + } + ], + "environments": [ + { + "id": "f3024d19-6939-4f2b-a9f8-52985c351a37", + "name": "token", + "variables": { + "4729bb8f-3723-442e-861c-632049d08f9a": { + "createdAt": "2022-11-07T16:59:33.356+07:00", + "name": "token", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NjgwNjkyMDIsImlhdCI6MTY2Nzk4MjgwMiwic3ViIjoxLCJ0eXBlIjoiYWNjZXNzIn0.-Io4nLnBsuJRVLvr3t3PcQV-M_b2HRaij5uxxJwIV1c", + "enabled": true, + "private": false + }, + "0ab103ed-c518-49fd-87e1-3135d12fe28d": { + "createdAt": "2022-11-07T16:59:33.356+07:00", + "name": "id", + "value": "1", + "enabled": true, + "private": false + }, + "31a8c7b1-ef83-476d-a685-dd906120124e": { + "createdAt": "2022-11-07T16:59:33.356+07:00", + "name": "refresh", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2Njc5MDg0MTYsImlhdCI6MTY2NzgyMjAxNiwic3ViIjoxLCJ0eXBlIjoicmVmcmVzaCJ9.18hC4yOyJRgu56BUhVxAF-tVLE3M6e82ZATpfuktDe8", + "enabled": true, + "private": false + } + } + } + ] +} \ No newline at end of file