diff --git a/LICENSE b/LICENSE index d41b8bd..54f0e21 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Ivan Goncharov +Copyright (c) 2020 MieuxVoter.fr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3661704..8265385 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,28 @@ # Mieux Voter OpenAPI Definition -TODO: -CI on Jenkins +This reposority hosts the **OpenAPI specifications** for the API of MieuxVoter, +a Majority Judgment polling application spearheaded by the french nonprofit +[MieuxVoter.fr](https://mieuxvoter.fr). + + +- APP (Prod) : https://app.mieuxvoter.fr +- API (Prod) : https://api.mieuxvoter.fr/v1 +- Sandbox : https://sandboxapi.mieuxvoter.fr/v1 + + +## Goal + +… + + +## TODO + +- [x] Draft a spec +- [ ] Use the spec +- [ ] Tweak the spec +- [ ] CI on Jenkins +- [ ] Localization (how?) +- [ ] … ## Working on your OpenAPI Definition @@ -22,12 +43,13 @@ Bundles the definition to the dist folder. #### `npm test` Validates the definition. + ## Contribution Guide -Below is a sample contribution guide. The tools -in the repository don't restrict you to any +Below is a sample contribution guide. The tools +in the repository don't restrict you to any specific structure. Adjust the contribution guide -to match your own structure. However, if you +to match your own structure. However, if you don't have a structure in mind, this is a good place to start. @@ -36,7 +58,7 @@ adjust the file/folder organization. The `.redocly.yaml` controls settings for various tools including the lint tool and the reference -docs engine. Open it to find examples and +docs engine. Open it to find examples and [read the docs](https://docs.redoc.ly/cli/configuration/) for more information. diff --git a/mv-openapi.yaml b/mv-openapi.yaml index 30ddd3b..e767afb 100644 --- a/mv-openapi.yaml +++ b/mv-openapi.yaml @@ -1,12 +1,12 @@ # Warning: this file has been automatically generated. All manual modifications will be lost, see README.md for details. openapi: 3.0.0 info: - title: Mieux Voter - description: A poll application based on Majority Judgment. + title: API Mieux Voter + description: "## What is this?\n\nAn _Application Programming Interface_ (API) for a polling application\nusing **Majority Judgment**.\n\nYou are looking at the specifications of the communication between server and clients, usually because you want to make your own client.\n\n### Help, I'm lost!\n\nBest head to the official application client, then:\n[Application MieuxVoter](https://app.mieuxvoter.fr).\nSee you there !\n\n\n## What is Majority Judgment?\n\nWe believe that it is the most elegant polling system that is available right now.\n\nIt was discovered in 2002 by \U0001F1EB\U0001F1F7 french researchers, and it comes from \U0001F377 wine \U0001F3C6 contests.\n\n\n## Contributing\n\n### I've found a bug!\n\nHead over to our [issues tracker](https://github.com/MieuxVoter/mv-api-spec/issues) with your ideas and contributions.\n\n### But I don't understand code!\n\nIt's okay, we need everyone!\nThere's lots you can do to help, such as translating, documenting, reporting issues, painting pixels, promoting majority judgment…\n\n### Shut up and take my money!\n\nDonations help us boost development : [Donate](https://mieuxvoter.fr/index.php/participer/).\n" version: 1.0.1-oas3 termsOfService: 'https://github.com/MieuxVoter' contact: - name: Mieux Voter app developpers team + name: Mieux Voter App Development Team email: app@mieuxvoter.fr servers: - url: 'https://api.mieuxvoter.fr/v1' @@ -17,7 +17,7 @@ paths: /polls: get: operationId: get-polls - summary: Gets all polls. + summary: Gets all polls responses: '200': description: OK @@ -29,7 +29,7 @@ paths: $ref: '#/components/schemas/poll' post: operationId: create-poll - summary: Creates a poll. + summary: Creates a poll requestBody: required: true content: @@ -59,7 +59,7 @@ paths: list-poll-results: $ref: '#/components/links/list-poll-results' '400': - description: Bad Request. Expect at least 2 proposals and a title. + description: Bad Request. Provide at least 2 proposals and a title. '/polls/{poll-id}': parameters: - in: path @@ -94,19 +94,23 @@ paths: - pollAuth: [] responses: '200': - description: OK + description: Poll was updated. content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/poll' + $ref: '#/components/schemas/poll' + '404': + $ref: '#/components/responses/poll-not-found' delete: operationId: delete-poll summary: Deletes a poll + description: > + All the Poll data will be permanently erased. This includes all the + corollary models (Tally, Ballots, …) Only the Poll's author may delete + it. (and wild admins) responses: '200': - description: OK + description: Poll was deleted. '404': $ref: '#/components/responses/poll-not-found' security: @@ -187,7 +191,7 @@ paths: type: string post: operationId: add-participant-to-poll - description: Add a participant to a poll + summary: Adds a participant to a poll requestBody: content: application/json: @@ -195,7 +199,7 @@ paths: $ref: '#/components/schemas/participant' responses: '200': - description: Invitation was sent + description: Invitation was sent. content: text/plain: schema: @@ -211,7 +215,7 @@ paths: type: string get: operationId: get-poll-participant - summary: Get a participant from a poll + summary: Gets a participant from a poll responses: '200': description: OK @@ -226,7 +230,7 @@ paths: - pollAuth: [] delete: operationId: delete-poll-participant - summary: Delete a participant from a poll + summary: Deletes a participant from a poll responses: '200': description: OK @@ -243,7 +247,7 @@ paths: type: string get: operationId: get-poll-results - description: Get results of a poll + summary: Gets results of a poll responses: '200': description: OK @@ -367,72 +371,95 @@ components: description: A unique identifier example: 4 readOnly: true - mention: + grade: type: integer - description: >- - The mention item, according to the mentions array defined when - creating the poll. + description: > + One grade of the grading defined when creating the poll. Zero (0) + means the worst grade, and it goes upwards from there, up to the + size of the grading, minus one. example: 2 proposal: type: object properties: id: - type: integer - description: A unique identifier. readOnly: true + type: integer + description: > + A unique identifier for the proposal, in the context of the poll. + This is not a globally unique identifier. example: 4 + uuid: + readOnly: true + type: string + format: uuid + description: | + A Universally Unique IDentifier for the proposal. (UUIDv4) + example: fa888652-727e-470b-817e-d77862a8d112 name: type: string - description: Unique but short name of the proposal. + description: | + Unique but short name of the proposal. No markup is allowed. example: A new school + description: + type: string + description: > + An optional, multiline description of the proposal. Commonmark + markdown is allowed. + example: This school would welcome 500 pupils. ballots: type: array - description: The ballots received by this proposal. + description: > + The ballots received by this proposal. Each participant may emit one + ballot (one judgment) per proposal. items: $ref: '#/components/schemas/ballot' - description: - type: string - description: An optional description of the proposal - example: This school would welcome 500 pupils. required: - name - mention: + grade: type: object properties: id: type: integer - description: A unique identifier + description: > + Unique identifier of the grade in its grading. Zero (0) is the worst + grade, and it goes upwards. example: 0 readOnly: true name: type: string - description: >- - Unique but short name of the mention, like *Excellent* or *To - reject*. - example: Excellent + description: | + Unique but short name of the grade, like "Excellent" or "To reject". + example: Good description: type: string - description: An optional description of the mention - example: 'In this poll, the mention *To reject* disqualifies the proposal.' + description: An optional description of the grade. + example: 'In this poll, the grade "To reject" disqualifies the proposal.' required: - name participant: type: object properties: id: + readOnly: true type: string description: A unique identifier. example: JtRm05yjMAuFCI2uwnFp - readOnly: true - description: + name: type: string - description: An optional description of the participant. - example: John Doe - has-participed: + maxLength: 32 + description: An optional name or pseudonym for the participant. + example: Jane Doe + email: + type: string + description: > + The electronic mail address that will eventually be created at the + creation of the participant (not kept in memory). + example: jane.doe@example.com + has-participated: type: boolean description: >- - True if the participant already participed to the poll, False - otherwise. + True if the participant already participated to the poll, False + otherwise example: true poll-id: type: string @@ -442,44 +469,59 @@ components: type: string description: The identifier of the user. example: 1jDe1e5eF_IkaYPuoIYX - mail: - type: string - description: >- - The mail that will eventually created at the creation of the - participant (not kept in memory). - example: john-doe@example.com required: - poll-id poll: type: object + description: > + A `Poll` is the core model of the application. + + A `Poll` exposes a list of `Proposal`s, and `Participant`s may + individually give each `Proposal` a `Grade`. (in a `Ballot`) properties: id: type: string - description: A unique identifier + description: A unique identifier. example: 1jDe1e5eF_IkaYPuoIYX readOnly: true + uuid: + type: string + format: uuid + pattern: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' + description: | + A Universally Unique IDentifier for the poll. (version 4) + example: bb788552-727d-470b-827e-d7796248d293 + readOnly: true title: type: string + description: The title of the poll. example: What project should our neighbourhood invest in for the next year? - description: The title of the poll description: type: string - description: A description of the poll - example: null + description: > + A lengthy description of the poll. In here should be stated the + constitutive details of the poll, whether it is informative or + imperative for example. + example: > + This poll will help decide which projects get the most attention and + budget so you should consider the proposals carefully and with + gumption. proposals: type: array - description: The proposals being voted in a poll. + description: > + The proposals being judged by the participants in a poll. It makes + no sense to have less than two proposals in a poll. minItems: 2 maxItems: 20 items: $ref: '#/components/schemas/proposal' - mentions: + grades: type: array - description: The mentions on which one participant vote to a proposal. + description: The grades on which one participant vote to a proposal. minItems: 2 maxItems: 10 items: - $ref: '#/components/schemas/mention' + $ref: '#/components/schemas/grade' participants: type: array description: The participants that are allowed to participate to the election. @@ -490,7 +532,7 @@ components: description: 'Organizer id. If not given, a dummy user is created.' restrict-participants: type: boolean - description: 'True if anyone can participate to this poll, False otherwise.' + description: 'True if anyone can participate in this poll, False otherwise.' example: false required: - title @@ -517,9 +559,9 @@ components: ranking: type: array description: >- - An array representing mentions level for each proposal, according to - the mentions list, following the order of the proposals array - defined when the related poll has been created. + An array representing grades level for each proposal, according to + the grades list, following the order of the proposals array defined + when the related poll has been created. example: - 0 - 6 diff --git a/openapi/DESCRIPTION.md b/openapi/DESCRIPTION.md new file mode 100644 index 0000000..0ed05cf --- /dev/null +++ b/openapi/DESCRIPTION.md @@ -0,0 +1,35 @@ +## What is this? + +An _Application Programming Interface_ (API) for a polling application +using **Majority Judgment**. + +You are looking at the specifications of the communication between server and clients, usually because you want to make your own client. + +### Help, I'm lost! + +Best head to the official application client, then: +[Application MieuxVoter](https://app.mieuxvoter.fr). +See you there ! + + +## What is Majority Judgment? + +We believe that it is the most elegant polling system that is available right now. + +It was discovered in 2002 by 🇫🇷 french researchers, and it comes from 🍷 wine 🏆 contests. + + +## Contributing + +### I've found a bug! + +Head over to our [issues tracker](https://github.com/MieuxVoter/mv-api-spec/issues) with your ideas and contributions. + +### But I don't understand code! + +It's okay, we need everyone! +There's lots you can do to help, such as translating, documenting, reporting issues, painting pixels, promoting majority judgment… + +### Shut up and take my money! + +Donations help us boost development : [Donate](https://mieuxvoter.fr/index.php/participer/). diff --git a/openapi/components/README.md b/openapi/components/README.md index 26eaeb5..b8e8513 100644 --- a/openapi/components/README.md +++ b/openapi/components/README.md @@ -1,5 +1,5 @@ Reusable components -=========== +=================== * You can create the following folders here: - `schemas` - reusable [Schema Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schemaObject) @@ -11,4 +11,4 @@ Reusable components - `links` - reusable [Link Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#linkObject) - `callbacks` - reusable [Callback Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#callbackObject) - `securitySchemes` - reusable [Security Scheme Objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#securitySchemeObject) -* Filename of files inside the folders represent component name, e.g. `Customer.yaml` +* Filename of files inside the folders represent component name, e.g. `customer.yaml` diff --git a/openapi/components/responses/ballot-not-found.yaml b/openapi/components/responses/ballot-not-found.yaml index e98c180..096bf0a 100644 --- a/openapi/components/responses/ballot-not-found.yaml +++ b/openapi/components/responses/ballot-not-found.yaml @@ -1,4 +1,4 @@ -description: The specified ballot was not found +description: The requested ballot was not found. content: application/json: schema: diff --git a/openapi/components/responses/participant-not-found.yaml b/openapi/components/responses/participant-not-found.yaml index 8e7e0dd..4d6649e 100644 --- a/openapi/components/responses/participant-not-found.yaml +++ b/openapi/components/responses/participant-not-found.yaml @@ -1,4 +1,4 @@ -description: The specified participant was not found +description: The requested participant was not found. content: application/json: schema: diff --git a/openapi/components/responses/poll-not-found.yaml b/openapi/components/responses/poll-not-found.yaml index 70684dd..55977ca 100644 --- a/openapi/components/responses/poll-not-found.yaml +++ b/openapi/components/responses/poll-not-found.yaml @@ -1,4 +1,4 @@ -description: The specified poll was not found +description: The requested poll was not found. content: application/json: schema: diff --git a/openapi/components/responses/unauthorized.yaml b/openapi/components/responses/unauthorized.yaml index 15dba9b..953a85a 100644 --- a/openapi/components/responses/unauthorized.yaml +++ b/openapi/components/responses/unauthorized.yaml @@ -1,4 +1,6 @@ -description: Unauthorized +description: > + Your are not authorized to do that operation. + Try logging in? If the problem persists, contact an administrator. content: application/json: schema: diff --git a/openapi/components/schemas/ballot.md b/openapi/components/schemas/ballot.md new file mode 100644 index 0000000..f9e9751 --- /dev/null +++ b/openapi/components/schemas/ballot.md @@ -0,0 +1,8 @@ + +A Ballot holds a single Grade given by a Participant to a Proposal of a Poll. + +A Ballot is a single Judgment. + +For security purposes, Ballots are journalized and may not be updated or deleted individually. +If you change your mind, emit a new Ballot. +It will be the responsibility of the Poll Tallier to only consider the latest ballot when there are multiple. diff --git a/openapi/components/schemas/ballot.yaml b/openapi/components/schemas/ballot.yaml index efb0644..11b2780 100644 --- a/openapi/components/schemas/ballot.yaml +++ b/openapi/components/schemas/ballot.yaml @@ -1,11 +1,21 @@ type: object +description: + $ref: ballot.md properties: + # UUIDv4, here ? id: type: integer description: A unique identifier example: 4 readOnly: true - mention: + grade: type: integer - description: The mention item, according to the mentions array defined when creating the poll. + description: > + Index of a grade of the poll's grading. + Zero (0) means the worst grade, and it goes upwards from there, + up to the size of the grading, minus one. example: 2 + pollId: + type: string + userId: + type: string diff --git a/openapi/components/schemas/error.yaml b/openapi/components/schemas/error.yaml index 24bdbcd..a00b44f 100644 --- a/openapi/components/schemas/error.yaml +++ b/openapi/components/schemas/error.yaml @@ -2,12 +2,12 @@ type: object properties: code: type: string - description: The HTTP code of the response + description: The HTTP code of the response. example: 404 message: type: string - description: The response details - example: The specified participant was not found + description: The response details. + example: The specified participant was not found. required: - code - message diff --git a/openapi/components/schemas/grade.yaml b/openapi/components/schemas/grade.yaml new file mode 100644 index 0000000..80c0123 --- /dev/null +++ b/openapi/components/schemas/grade.yaml @@ -0,0 +1,26 @@ +type: object +properties: + id: + type: integer + description: > + Identifier of the grade. + example: 0 + readOnly: true + name: + type: string + description: > + Short yet unique name of the grade, like "Excellent" or "To reject". + example: Good + description: + type: string + description: An optional description of the grade. + example: In this poll, the grade "To reject" disqualifies the proposal. + level: + type: integer + description: | + Unique level of the grade in its grading. + Zero (0) is the worst grade, and it goes upwards. + Each grade of a poll must have a unique level. +required: + - name + - level diff --git a/openapi/components/schemas/mention.yaml b/openapi/components/schemas/mention.yaml deleted file mode 100644 index dc84d6c..0000000 --- a/openapi/components/schemas/mention.yaml +++ /dev/null @@ -1,17 +0,0 @@ -type: object -properties: - id: - type: integer - description: A unique identifier - example: 0 - readOnly: true - name: - type: string - description: Unique but short name of the mention, like *Excellent* or *To reject*. - example: Excellent - description: - type: string - description: An optional description of the mention - example: In this poll, the mention *To reject* disqualifies the proposal. -required: - - name diff --git a/openapi/components/schemas/participant.md b/openapi/components/schemas/participant.md new file mode 100644 index 0000000..b4f2a7b --- /dev/null +++ b/openapi/components/schemas/participant.md @@ -0,0 +1,4 @@ + +Invitation to participate + +Poll participants are the actual users that participated. diff --git a/openapi/components/schemas/participant.yaml b/openapi/components/schemas/participant.yaml index 05d7f1b..6fb7ace 100644 --- a/openapi/components/schemas/participant.yaml +++ b/openapi/components/schemas/participant.yaml @@ -1,17 +1,25 @@ type: object +description: + $ref: 'participant.md' properties: id: + readOnly: true type: string description: A unique identifier. example: JtRm05yjMAuFCI2uwnFp - readOnly: true - description: + name: + type: string + maxLength: 32 + description: An optional name or pseudonym for the participant. + example: Jane Doe + email: type: string - description: An optional description of the participant. - example: John Doe - has-participed: + description: > + The electronic mail address that will eventually be created at the creation of the participant (not kept in memory). + example: jane.doe@example.com + has-participated: type: boolean - description: True if the participant already participed to the poll, False otherwise. + description: True if the participant already participated to the poll, False otherwise example: true poll-id: type: string @@ -21,9 +29,6 @@ properties: type: string description: The identifier of the user. example: 1jDe1e5eF_IkaYPuoIYX - mail: - type: string - description: The mail that will eventually created at the creation of the participant (not kept in memory). - example: john-doe@example.com + required: - poll-id diff --git a/openapi/components/schemas/poll-new.yaml b/openapi/components/schemas/poll-new.yaml new file mode 100644 index 0000000..c0e97de --- /dev/null +++ b/openapi/components/schemas/poll-new.yaml @@ -0,0 +1,9 @@ +type: object +description: + $ref: 'poll.md' +properties: + $ref: 'poll-properties.yaml' +required: + - subject + - proposals + - grades diff --git a/openapi/components/schemas/poll-properties.yaml b/openapi/components/schemas/poll-properties.yaml new file mode 100644 index 0000000..e1e0716 --- /dev/null +++ b/openapi/components/schemas/poll-properties.yaml @@ -0,0 +1,69 @@ +# These properties are shared between poll schemes +id: + readOnly: true + type: string + description: | + A unique identifier for the poll. + That identifier has a fixed length of 20 alphanumerical characters, + including some special characters like `_`. + pattern: '[0-9a-fA-F_]{20}' + example: 1jDe1e5eF_IkaYPuoIYX +subject: + type: string + description: The subject of the poll. + example: What project should our neighbourhood invest in for the next year? +description: + type: string + description: > + A lengthy description of the poll. + In here should be stated the constitutive details of the poll, + whether it is informative or imperative for example. + example: > + This poll will help decide which projects get the most attention and budget + so you should consider the proposals carefully and with gumption. +proposals: + type: array + description: > + The proposals being judged by the participants of the poll. + It makes no sense to have less than two proposals in a poll. + minItems: 2 + maxItems: 256 + items: + $ref: ./proposal.yaml +grades: + type: array + description: | + The grades that participants may give to each proposal. + The grades should be **non-ambiguously ordinal**, + ie. their ranking should be obvious to everyone. + + #### Good examples + - DISAPPROVED, APPROVED + - TO REJECT, POOR, PASSABLE, GOOD, VERY GOOD, EXCELLENT + - BORING, ENTERTAINING, FUN, AMAZING (to be discussed) + + #### Bad examples + - LOUSY, MEDIOCRE, OKAY, GOOD, FINE, PEACHY + - BORING, BEAUTIFUL, FUN, MAGNIFICIENT + minItems: 2 + maxItems: 16 + items: + $ref: ./grade.yaml +participants: + type: array + description: | + The participants that are allowed to participate in the poll. + That property is ignored if `restrict_participants` is `false`. + + --- + + Or should this be the list of the participants of the poll? + items: + $ref: ./participant.yaml +user-id: + type: string + description: Organizer id. If not given, a dummy user is created. +restrict-participants: + type: boolean + description: True if anyone can participate in this poll, False otherwise. + example: false diff --git a/openapi/components/schemas/poll.md b/openapi/components/schemas/poll.md new file mode 100644 index 0000000..7a5e1cb --- /dev/null +++ b/openapi/components/schemas/poll.md @@ -0,0 +1,2 @@ +A `Poll` is the core model of the application. +A `Poll` has a subject exposes a list of `Proposal`s, and `Participant`s may individually give each `Proposal` a `Grade`. (in a `Ballot`) diff --git a/openapi/components/schemas/poll.yaml b/openapi/components/schemas/poll.yaml index 3f20575..4c921ee 100644 --- a/openapi/components/schemas/poll.yaml +++ b/openapi/components/schemas/poll.yaml @@ -1,44 +1,5 @@ type: object +description: + $ref: 'poll.md' properties: - id: - type: string - description: A unique identifier - example: 1jDe1e5eF_IkaYPuoIYX - readOnly: true - title: - type: string - example: What project should our neighbourhood invest in for the next year? - description: The title of the poll - description: - type: string - description: A description of the poll - example: - proposals: - type: array - description: The proposals being voted in a poll. - minItems: 2 - maxItems: 20 - items: - $ref: ./proposal.yaml - mentions: - type: array - description: The mentions on which one participant vote to a proposal. - minItems: 2 - maxItems: 10 - items: - $ref: ./mention.yaml - participants: - type: array - description: The participants that are allowed to participate to the election. - items: - $ref: ./participant.yaml - user-id: - type: string - description: Organizer id. If not given, a dummy user is created. - restrict-participants: - type: boolean - description: True if anyone can participate to this poll, False otherwise. - example: false -required: - - title - - proposals + $ref: 'poll-properties.yaml' diff --git a/openapi/components/schemas/proposal.yaml b/openapi/components/schemas/proposal.yaml index 143e144..bdd788e 100644 --- a/openapi/components/schemas/proposal.yaml +++ b/openapi/components/schemas/proposal.yaml @@ -1,22 +1,40 @@ +# Thing unto which the participants pass judgments. +# Also known as Candidate. type: object properties: id: - type: integer - description: A unique identifier. readOnly: true + type: integer + description: > + A unique identifier for the proposal, in the context of the poll. + This is not a globally unique identifier. example: 4 + uuid: + readOnly: true + type: string + format: uuid + description: > + A Universally Unique IDentifier for the proposal. (UUIDv4) + example: fa888652-727e-470b-817e-d77862a8d112 name: type: string - description: Unique but short name of the proposal. + description: > + Unique but short name of the proposal. + No markup is allowed. example: A new school + description: + type: string + description: > + An optional, multiline description of the proposal. + Commonmark markdown is allowed. + example: This school would welcome 500 pupils. ballots: type: array - description: The ballots received by this proposal. + description: > + The ballots received by this proposal. + Each participant may emit one ballot (one judgment) per proposal. items: $ref: ./ballot.yaml - description: - type: string - description: An optional description of the proposal - example: This school would welcome 500 pupils. + required: - name diff --git a/openapi/components/schemas/result.yaml b/openapi/components/schemas/result.yaml index 8f9f873..5f7829b 100644 --- a/openapi/components/schemas/result.yaml +++ b/openapi/components/schemas/result.yaml @@ -4,8 +4,9 @@ properties: $ref: ./poll.yaml ranking: type: array - description: An array representing mentions level for each proposal, - according to the mentions list, following the order of the proposals array + description: | + An array representing grades level for each proposal, + according to the grades list, following the order of the proposals array defined when the related poll has been created. example: [0, 6, 3, 2, 2] minItems: 2 diff --git a/openapi/components/schemas/user.yaml b/openapi/components/schemas/user.yaml index 2a46796..b9b60e0 100644 --- a/openapi/components/schemas/user.yaml +++ b/openapi/components/schemas/user.yaml @@ -1,15 +1,28 @@ +# Whether you participate or organize, you're a User. type: object properties: id: - type: integer - description: A unique identifier - example: 0 - readOnly: true - name: type: string - description: Unique user-name - example: john.doe - description: + description: | + A unique identifier. + That identifier has a fixed length of 10 alphanumerical characters, + as well as `_` and `-`. + pattern: '[abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ0-9_-]{10}' + example: 1jDe2e57_F + username: type: string - description: An optional description of the user - example: John Doe is a multiple-use name that is used when the true name of a person is unknown or is being intentionally concealed + # To support all unicode letters, can we use `\p{L}` instead? + pattern: '[a-zA-Z0-9._-]{3,21}' + description: > + Unique username, chosen by the user. + May only contain alphanumeric latin characters without diacritics and `.`, `-` or `_`. + example: john.doe.41 + password: + type: string + format: password + description: > + Hash of the password chosen by the user. + # description: + # type: string + # description: An optional description of the user + # example: John Doe is a multiple-use name that is used when the true name of a person is unknown or is being intentionally concealed diff --git a/openapi/mv-openapi-root.yaml b/openapi/mv-openapi-root.yaml index 0216316..b01fe42 100644 --- a/openapi/mv-openapi-root.yaml +++ b/openapi/mv-openapi-root.yaml @@ -1,11 +1,12 @@ openapi: 3.0.0 info: - title: Mieux Voter - description: A poll application based on Majority Judgment. + title: API Mieux Voter + description: + $ref: 'DESCRIPTION.md' version: 1.0.1-oas3 termsOfService: 'https://github.com/MieuxVoter' contact: - name: Mieux Voter app developpers team + name: Mieux Voter App Development Team email: app@mieuxvoter.fr servers: - url: 'https://api.mieuxvoter.fr/v1' @@ -31,11 +32,32 @@ paths: $ref: paths/users.yaml '/users/{user-id}': $ref: 'paths/users@{user-id}.yaml' +tags: + - name: User Management + description: | + All the paths for: + - user creation + - authentication + - security + - trust levels + - name: Poll Indexation + description: > + Paths about indexing (public) polls. + - name: Poll Organization + description: > + Paths about organizing a poll. + - name: Poll Participation + description: > + Paths about participating to a poll. + - name: Poll Deliberation + description: > + Paths about deliberating using a poll. components: securitySchemes: participantAuth: type: http scheme: bearer + # organizerAuth pollAuth: type: http scheme: bearer @@ -45,3 +67,6 @@ components: userAuth: type: http scheme: bearer + adminAuth: + type: http + scheme: bearer diff --git a/openapi/paths/polls.yaml b/openapi/paths/polls.yaml index cbd1523..fd9799e 100644 --- a/openapi/paths/polls.yaml +++ b/openapi/paths/polls.yaml @@ -1,6 +1,11 @@ get: operationId: get-polls - summary: Gets all polls. + summary: Gets all polls + description: | + Gets all polls that were marked as publicly accessible. + Polls only accessible by invitation or link will not be returned. + tags: + - Poll Indexation responses: '200': description: OK @@ -12,13 +17,15 @@ get: $ref: ../components/schemas/poll.yaml post: operationId: create-poll - summary: Creates a poll. + summary: Creates a poll + tags: + - Poll Organization requestBody: required: true content: application/json: schema: - $ref: ../components/schemas/poll.yaml + $ref: ../components/schemas/poll-new.yaml responses: '201': description: Created @@ -42,4 +49,4 @@ post: list-poll-results: $ref: ../components/links/list-poll-results.yaml '400': - description: Bad Request. Expect at least 2 proposals and a title. + description: Bad Request. Provide at least 2 proposals and a title. diff --git a/openapi/paths/polls@{poll-id}.yaml b/openapi/paths/polls@{poll-id}.yaml index 2e575d0..8c859de 100644 --- a/openapi/paths/polls@{poll-id}.yaml +++ b/openapi/paths/polls@{poll-id}.yaml @@ -8,6 +8,9 @@ parameters: get: operationId: get-poll summary: Gets a poll by ID + tags: + - Poll Organization + - Poll Participation responses: '200': description: OK @@ -20,6 +23,8 @@ get: patch: operationId: update-poll summary: Updates a poll + tags: + - Poll Organization requestBody: required: true content: @@ -31,19 +36,25 @@ patch: - pollAuth: [] responses: '200': - description: OK + description: Poll was updated. content: application/json: schema: - type: array - items: - $ref: ../components/schemas/poll.yaml + $ref: ../components/schemas/poll.yaml + '404': + $ref: ../components/responses/poll-not-found.yaml delete: operationId: delete-poll summary: Deletes a poll + description: > + All the Poll data will be permanently erased. + This includes all the corollary models (Tally, Ballots, …) + Only the Poll's author may delete it. (and wild admins) + tags: + - Poll Organization responses: '200': - description: OK + description: Poll was deleted. '404': $ref: ../components/responses/poll-not-found.yaml security: diff --git a/openapi/paths/polls@{poll-id}@ballots.yaml b/openapi/paths/polls@{poll-id}@ballots.yaml index 4b44f14..146acfa 100644 --- a/openapi/paths/polls@{poll-id}@ballots.yaml +++ b/openapi/paths/polls@{poll-id}@ballots.yaml @@ -7,6 +7,8 @@ parameters: post: operationId: create-ballot summary: Creates a ballot + tags: + - Poll Participation requestBody: required: true content: @@ -26,7 +28,7 @@ post: properties: id: type: string - description: Id of the created ballot. + description: Identifier of the created ballot. links: get-ballot: $ref: ../components/links/get-ballot.yaml diff --git a/openapi/paths/polls@{poll-id}@ballots@{ballot-id}.yaml b/openapi/paths/polls@{poll-id}@ballots@{ballot-id}.yaml index e22948e..29fcb6e 100644 --- a/openapi/paths/polls@{poll-id}@ballots@{ballot-id}.yaml +++ b/openapi/paths/polls@{poll-id}@ballots@{ballot-id}.yaml @@ -12,6 +12,9 @@ parameters: get: operationId: get-ballot summary: Gets a ballot by ID + tags: + - Poll Deliberation + - Poll Participation responses: '200': description: A ballot object @@ -22,6 +25,8 @@ get: delete: operationId: delete-ballot summary: Deletes a ballot + tags: + - Poll Participation responses: '200': description: OK diff --git a/openapi/paths/polls@{poll-id}@participants.yaml b/openapi/paths/polls@{poll-id}@participants.yaml index bc18c27..f4c3dd8 100644 --- a/openapi/paths/polls@{poll-id}@participants.yaml +++ b/openapi/paths/polls@{poll-id}@participants.yaml @@ -6,7 +6,7 @@ parameters: type: string post: operationId: add-participant-to-poll - description: Add a participant to a poll + summary: Adds a participant to a poll requestBody: content: application/json: @@ -14,7 +14,7 @@ post: $ref: ../components/schemas/participant.yaml responses: '200': - description: Invitation was sent + description: Invitation was sent. content: text/plain: schema: diff --git a/openapi/paths/polls@{poll-id}@participants@{participant-id}@.yaml b/openapi/paths/polls@{poll-id}@participants@{participant-id}@.yaml index 5bdbca0..e92ca49 100644 --- a/openapi/paths/polls@{poll-id}@participants@{participant-id}@.yaml +++ b/openapi/paths/polls@{poll-id}@participants@{participant-id}@.yaml @@ -6,7 +6,7 @@ parameters: type: string get: operationId: get-poll-participant - summary: Get a participant from a poll + summary: Gets a participant from a poll responses: '200': description: OK @@ -21,7 +21,7 @@ get: - pollAuth: [] delete: operationId: delete-poll-participant - summary: Delete a participant from a poll + summary: Deletes a participant from a poll responses: '200': description: OK diff --git a/openapi/paths/polls@{poll-id}@results.yaml b/openapi/paths/polls@{poll-id}@results.yaml index 8746428..8aec8e0 100644 --- a/openapi/paths/polls@{poll-id}@results.yaml +++ b/openapi/paths/polls@{poll-id}@results.yaml @@ -6,7 +6,9 @@ parameters: type: string get: operationId: get-poll-results - description: Get results of a poll + summary: Gets the results of a poll + tags: + - Poll Deliberation responses: '200': description: OK diff --git a/openapi/paths/users.yaml b/openapi/paths/users.yaml index f4e24e0..7076045 100644 --- a/openapi/paths/users.yaml +++ b/openapi/paths/users.yaml @@ -1,6 +1,9 @@ +# get: operationId: get-users - summary: Gets all users. + summary: Gets all users + tags: + - User Management responses: '200': description: OK @@ -10,9 +13,13 @@ get: type: array items: $ref: ../components/schemas/user.yaml + security: + - adminAuth: [] post: operationId: create-user summary: Creates an user + tags: + - User Management requestBody: required: true content: diff --git a/openapi/paths/users@{user-id}.yaml b/openapi/paths/users@{user-id}.yaml index 2cdf85a..124f77a 100644 --- a/openapi/paths/users@{user-id}.yaml +++ b/openapi/paths/users@{user-id}.yaml @@ -8,6 +8,8 @@ parameters: get: operationId: get-user summary: Gets a user by ID + tags: + - User Management responses: '200': description: OK @@ -20,6 +22,8 @@ get: patch: operationId: update-user summary: Updates a user + tags: + - User Management requestBody: required: true content: @@ -41,6 +45,8 @@ patch: delete: operationId: delete-user summary: Deletes a user + tags: + - User Management responses: '200': description: OK diff --git a/package-lock.json b/package-lock.json index 3cca84a..5abfb4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "mieux-voter", + "name": "mieux-voter-openapi", "version": "1.0.0", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index 93439db..96dd09f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,27 @@ { - "name": "mieux-voter", + "name": "mieux-voter-openapi", "version": "1.0.0", + "description": "OpenAPI specifications for a Majority Judgment polling application made by MieuxVoter.fr", + "keywords": [ + "majority", + "judgment", + "poll", + "polling", + "api", + "rest", + "openapi", + "democracy", + "vote", + "libre", + "open" + ], + "homepage": "https://github.com/MieuxVoter/mv-api-spec", + "bugs": "https://github.com/MieuxVoter/mv-api-spec/issues", + "repository": { + "type": "git", + "url": "https://github.com/MieuxVoter/mv-api-spec.git" + }, + "license": "MIT", "dependencies": { "@redocly/openapi-cli": "^0.12.10" },