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

[FEATURE] Add support for writeOnly and readOnly openAPI 3.0.3 properties #487

Closed
mfrischbutter opened this issue Nov 9, 2022 · 11 comments · Fixed by #694
Closed

[FEATURE] Add support for writeOnly and readOnly openAPI 3.0.3 properties #487

mfrischbutter opened this issue Nov 9, 2022 · 11 comments · Fixed by #694
Assignees
Labels
enhancement New feature or request

Comments

@mfrischbutter
Copy link
Contributor

Is your feature request related to a problem? Please describe.
Since openAPI 3.0.3 there is the possibility to use one schema for the response and request at the same time. With the help of the onlyWrite and onlyRead properties, you can specify whether these properties should only be used in the response or in the request.

Our Django Rest Api currently only generates with these properties, since our move to openAPI 3.0.3. This makes this generator unusable in some places.

Describe the solution you'd like
If such properties are used in a schema, then two different models should be generated which end with Response or Request in their class names.

Example swagger.yaml

openapi: 3.0.3
info:
  title: Test API
  version: 0.13.0
  description: Test
paths:
  /api/token/:
    post:
      operationId: api_token_create
      description: |-
        Authentication Endpoint for the app
        This endpoint can generate Tokens for anyone who is permitted to use the app
      tags:
        - api
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/JSONWebToken'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/JSONWebToken'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/JSONWebToken'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JSONWebToken'
          description: ''
components:
  schemas:
    JSONWebToken:
      type: object
      description: |-
        Serializer class used to validate a username and password.

        Returns a JSON Web Token that can be used to authenticate later calls.
      properties:
        password:
          type: string
          writeOnly: true
        token:
          type: string
          readOnly: true
        email:
          type: string
          writeOnly: true
      required:
        - email
        - password
        - token

Swagger specification link
https://swagger.io/specification/
Bildschirm­foto 2022-11-09 um 14 38 44

@mfrischbutter mfrischbutter added the enhancement New feature or request label Nov 9, 2022
@Vovanella95
Copy link
Collaborator

Hi @mfrischbutter, will handle it during week

@ankit-triomics
Copy link

@Vovanella95 any updates on this?

@mfrischbutter
Copy link
Contributor Author

@ankit-triomics

No idea what the status is here, but for the meantime we were able to solve this by finding an option in our swagger generator in the backend to work around this issue.

If you have your Swagger API generated as well, you might want to look for it there as well.

The generator we use for Angular seems to have the same problem and WriteOnly doesn't seem to be implemented everywhere yet.

In our generator for Django, there is an option to generate the API without writeOnly and readOnly.

Maybe this helps.

@ankit-triomics
Copy link

@mfrischbutter thanks for the information, we use Django as well so this definitely helps.

@Vovanella95
Copy link
Collaborator

Vovanella95 commented Dec 8, 2022

Hi @ankit-triomics @mfrischbutter sorry for now answer for long time.

This would be great feature, but we already generating all fields final. It's immutable. I don't see how it can break any logic. Write-only fields? Why just not configure fields in correct way and send it?

We already generate all fields final, so it's read only.

Do you really need write-only fields? It will be really hard to support and from my perspective it's overhead

@mfrischbutter
Copy link
Contributor Author

For my side we can leave it as it is. Our swagger generator had the option to disable these fields on generation, so this is not an issue anymore.
So for the next one running into this issue, check your backend swagger generator. There is most likely an option to disable writeOnly and readOnly fields on generation.

Even the swagger generator for angular that we are using, does not support these fields. So I think we should be fine, if we ignore that for now.

@mfrischbutter mfrischbutter closed this as not planned Won't fix, can't repro, duplicate, stale Dec 8, 2022
@Vovanella95
Copy link
Collaborator

@mfrischbutter Yes, sorry, but it will be really expensive to support it.

we should generate private field and setter for such fields, also reimplement copyWith method and other things. Not now :)

@Vovanella95 Vovanella95 reopened this Dec 8, 2023
@Vovanella95
Copy link
Collaborator

@mfrischbutter reopening issue. Looks like it's needed one :D

@Vovanella95
Copy link
Collaborator

Hi again @mfrischbutter , I've tried to implement this feature but faced with a problem. I've generated class like this:

@JsonSerializable(explicitToJson: true)
class JSONWebToken {
  const JSONWebToken(
    this._token, {
    required this.password,
    required this.email,
  });

  factory JSONWebToken.fromJson(Map<String, dynamic> json) =>
      _$JSONWebTokenFromJson(json);

  static const toJsonFactory = _$JSONWebTokenToJson;
  Map<String, dynamic> toJson() => _$JSONWebTokenToJson(this);

  @JsonKey(name: 'password', includeIfNull: false)
  final String password;
  @JsonKey(name: 'token', includeIfNull: false)
  final String _token;
  String get token => _token;
  @JsonKey(name: 'email', includeIfNull: false)
  final String email;
  static const fromJsonFactory = _$JSONWebTokenFromJson;

  @override
  bool operator ==(dynamic other) {
    return identical(this, other) ||
        (other is JSONWebToken &&
            (identical(other.password, password) ||
                const DeepCollectionEquality()
                    .equals(other.password, password)) &&
            (identical(other._token, _token) ||
                const DeepCollectionEquality().equals(other._token, _token)) &&
            (identical(other.email, email) ||
                const DeepCollectionEquality().equals(other.email, email)));
  }

  @override
  String toString() => jsonEncode(this);

  @override
  int get hashCode =>
      const DeepCollectionEquality().hash(password) ^
      const DeepCollectionEquality().hash(_token) ^
      const DeepCollectionEquality().hash(email) ^
      runtimeType.hashCode;
}

Looks good, but json_serializable package doesn't want to generate code for this. It says Cannot populate the required constructor argument: _token. It is assigned to a private field. package:example/swagger_generated_code/some_file_2.swagger.dart:66:9.

Could you provide the way of generation of read-only fields? For now, I have no idea how to do this

@Vovanella95
Copy link
Collaborator

@mfrischbutter We decided to generate all readOnly fields nullable. It should be a solution

@Vovanella95
Copy link
Collaborator

Hi @ankit-triomics , @mfrischbutter , I've implemented this feature.

For now, all readOnly and writeOnly fields will be nullable and not required. It will give you ability to not send and not receive these properties.

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

Successfully merging a pull request may close this issue.

4 participants