Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement security fields from openapi to malli route data. #14

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

JohanCodinha
Copy link
Contributor

No description provided.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
…e-vector] pairs.
@lispyclouds
Copy link
Owner

thanks! will have a look asap!

@JohanCodinha
Copy link
Contributor Author

JohanCodinha commented Jan 23, 2025

Implement security as a malli route data, this can then be read by interceptor / midleware.

Given a doc like:

openapi: 3.1.0
info:
  title: Simple User Listing API
  description: A simple API to list users, where each user has an ID, and optional email/name.
  termsOfService: http://example.com/terms/
  contact:
    email: [email protected]
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-1.0.html
  version: "1.0.0"

servers:
  - url: https://api.example.com/v1
    description: Main production server

tags:
  - name: user
    description: Operations about user

paths:
  /users:
    get:
      tags:
        - user
      summary: List all users
      description: Returns all registered users.
      operationId: listUsers
      # Declare that this endpoint requires the sessionCookieAuth security scheme
      security:
        - sessionCookieAuth: ["read:user"]
        - test: ["one:two"]
      responses:
        '200':
          description: A list of user objects
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
        '400':
          description: Bad request
        '401':
          description: Unauthorized (no valid session cookie)
        '403':
          description: Forbidden (logged in, but not allowed to access this resource)

components:
  securitySchemes:
    # A simple cookie-based auth scheme named sessionCookieAuth
    sessionCookieAuth:
      type: apiKey
      in: cookie
      name: session
      description: >
        A session-based authentication scheme. The cookie must contain
        a valid session ID that identifies the user.
  schemas:
    User:
      type: object
      required:
        - id
      properties:
        id:
          type: string
          format: uuid
          description: The unique identifier for a user
        email:
          type: string
          description: Optional email address of the user
        name:
          type: string
          description: Optional name of the user

Produce routes like:

[["/users"
  {:get
   {:handler #function[routes/fn--23261],
    :responses
    {200
     {:content
      {"application/json"
       {:schema
        [:sequential
         [:map
          {:closed false}
          [:id #function[clojure.core/uuid?]]
          [:email {:optional true} #function[clojure.core/string?--5494]]
          [:name {:optional true} #function[clojure.core/string?--5494]]]]}},
      :description "A list of user objects"},
     400 {:content {:default {:schema #function[clojure.core/nil?]}}, :description "Bad request"},
     401
     {:content {:default {:schema #function[clojure.core/nil?]}},
      :description "Unauthorized (no valid session cookie)"},
     403
     {:content {:default {:schema #function[clojure.core/nil?]}},
      :description "Forbidden (logged in, but not allowed to access this resource)"}},
    :security [["sessionCookieAuth" ["read:user"]]
                   ["test" ["one:two"]]]}}]]

@JohanCodinha
Copy link
Contributor Author

Need to add a test, only tested at the repl with no security info, with 1 and with many.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@@ -5,6 +5,7 @@
; https://opensource.org/licenses/MIT.

{:deps {io.swagger.parser.v3/swagger-parser {:mvn/version "2.1.25"}}
:paths ["resources" "src"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this and put the test dir? in something like a specs dir maybe. we can just use (slurp "specs/security-users.yml"). I'd rather not have things that aren't part of the final artifact in resources.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it makes sense I just added this to have a repl going.

(->> security-reqs
(mapcat seq)
(map (juxt key val))
(into [])))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this into can be dropped for a mapv before this?

Copy link
Owner

@lispyclouds lispyclouds Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thinking more, is this conversion even needed or does is just work in reitit as its all Maps and Lists anyways?

Copy link
Contributor Author

@JohanCodinha JohanCodinha Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just creating route data. It won't work in reitit until you add middleware that uses that data.
Although it's opinionated, I chose to represent it as a vector of vectors because it convey the logical OR of having multiple security schemes.
This could have been a map but I think of map a as AND.
And yes, this can also be done with a mapv, feel free to change it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Let's add some docs about it on the README.

"listUsersSingle" (constantly :ok)
"listUsersNoScope" (constantly :ok)
"listUsersNoSecurity" (constantly :ok)}
api-spec (slurp (io/resource "security-users.yml"))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets use a slurp without the resource like mentioned before

@lispyclouds
Copy link
Owner

Rest looks pretty good! thanks!

lispyclouds added a commit that referenced this pull request Jan 31, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@lispyclouds
Copy link
Owner

@JohanCodinha can I get some reitit middleware/interceptor examples for the readme thst uses this? I'm happy to merge this after that. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants