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

Change OpenAPI backend generator config #4376

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/comments_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ def do_post(self, **kwargs) -> dict[str, str]:
user = self.get_current_user(required=True)

comment_request = CommentsRequest.from_dict(self.request.json)
if not comment_request:
self.abort(400, msg='Invalid request')
comment_content = comment_request.comment
if not comment_content:
self.abort(400, msg='Comment content is required')
post_to_thread_type = comment_request.post_to_thread_type

if comment_content:
Expand Down Expand Up @@ -128,6 +132,8 @@ def do_post(self, **kwargs) -> dict[str, str]:

def do_patch(self, **kwargs) -> dict[str, str]:
patch_request = PatchCommentRequest.from_dict(self.request.json)
if not patch_request:
self.abort(400, msg='Invalid request')
comment: Activity = Activity.get_by_id(patch_request.comment_id)

user = self.get_current_user(required=True)
Expand Down
4 changes: 4 additions & 0 deletions api/component_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def do_get(self, **kwargs):
@permissions.require_admin_site
def do_put(self, **kwargs) -> tuple[dict, int]:
component_users_request = ComponentUsersRequest.from_dict(self.request.get_json(force=True))
if not component_users_request:
self.abort(400, 'Invalid request')
self.__update_subscribers_list(True, user_id=kwargs.get('user_id', None),
blink_component_id=kwargs.get('component_id', None),
primary=component_users_request.owner)
Expand All @@ -59,6 +61,8 @@ def do_put(self, **kwargs) -> tuple[dict, int]:
def do_delete(self, **kwargs) -> tuple[dict, int]:
params = self.request.get_json(force=True)
component_users_request = ComponentUsersRequest.from_dict(params)
if not component_users_request:
self.abort(400, 'Invalid request')
self.__update_subscribers_list(False, user_id=kwargs.get('user_id', None),
blink_component_id=kwargs.get('component_id', None),
primary=component_users_request.owner)
Expand Down
3 changes: 2 additions & 1 deletion api/login_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ def do_get(self, **kwargs):
self.abort(405, valid_methods=['POST'])

def do_post(self, **kwargs):
token = None
try:
request = SignInRequest.from_dict(self.request.json)
token = request.credential
if not token:
raise werkzeug.exceptions.BadRequest(description="Missing required field 'credential'")
message = "Unable to Authenticate. Please sign in again."
except ValueError:
message = "Invalid Request"
raise werkzeug.exceptions.BadRequest(description="Invalid Request") # Properly raise error

try:
idinfo = google.oauth2.id_token.verify_oauth2_token(
Expand Down
2 changes: 1 addition & 1 deletion api/permissions_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_get__anon(self):
testing_config.sign_out()
with test_app.test_request_context(self.request_path):
actual = self.handler.do_get()
self.assertEqual({'user': None}, actual)
self.assertEqual({}, actual)

def test_get__non_googler(self):
"""Non-googlers have no permissions by default"""
Expand Down
12 changes: 6 additions & 6 deletions api/review_latency_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@
import collections
import logging
from datetime import datetime, timedelta
from typing import Iterable, Any
from google.cloud import ndb # type: ignore
from typing import Any, Iterable

from chromestatus_openapi.models.feature_link import FeatureLink
from chromestatus_openapi.models.gate_latency import GateLatency
from chromestatus_openapi.models.review_latency import ReviewLatency
from google.cloud import ndb # type: ignore

from framework import basehandlers
from internals import slo
from internals.core_enums import *
from internals.core_models import FeatureEntry
from internals.review_models import Gate


DEFAULT_RECENT_DAYS = 90
# This means that the feature team has not yet requested this review.
NOT_STARTED_LATENCY = -1
Expand Down Expand Up @@ -132,9 +131,10 @@ def convert_to_result_format(
result: list[dict[str, Any]] = []
for fe in sorted_features:
latencies = latencies_by_fid[fe.key.integer_id()]
review_latency = ReviewLatency(
FeatureLink(fe.key.integer_id(), fe.name),
[GateLatency(gate_type, days)
review_latency = ReviewLatency.model_construct(feature=
FeatureLink.model_construct(id=fe.key.integer_id(), name=fe.name),
gate_reviews=
[GateLatency.model_construct(gate_type=gate_type, latency_days=days)
for (gate_type, days) in latencies]
)
result.append(review_latency.to_dict())
Expand Down
18 changes: 15 additions & 3 deletions api/reviews_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ def do_get(self, **kwargs) -> dict[str, list[dict[str, Any]]]:
# Note: We assume that anyone may view approvals.
votes = Vote.get_votes(feature_id=feature_id, gate_id=gate_id)
dicts = [converters.vote_value_to_json_dict(v) for v in votes]
return GetVotesResponse.from_dict({'votes': dicts}).to_dict()
response = GetVotesResponse.from_dict({'votes': dicts})
if not response:
logging.error(f"unable to convert response from get_votes to GetVotesResponse dicts={dicts}")
return self.abort(500)
return response.to_dict()

def do_post(self, **kwargs) -> dict[str, str]:
"""Set a user's vote value for the specified feature and gate."""
Expand Down Expand Up @@ -146,16 +150,24 @@ def do_get(self, **kwargs) -> dict[str, Any]:
approvers = approval_defs.get_approvers(g['gate_type'])
g['possible_assignee_emails'] = approvers

return GetGateResponse.from_dict({
response = GetGateResponse.from_dict({
'gates': dicts,
}).to_dict()
})
if not response:
logging.error(f"unable to convert response from get_votes to GetGateResponse dicts={dicts}")
return self.abort(500)
return response.to_dict()

def do_post(self, **kwargs) -> dict[str, str]:
"""Set the assignees for a gate."""
user, fe, gate, feature_id, gate_id = get_user_feature_and_gate(
self, kwargs)
request = PostGateRequest.from_dict(self.request.json)
if not request:
self.abort(400, msg='Invalid request')
assignees = request.assignees
if not assignees:
self.abort(400, msg='No assignees provided')

self.require_permissions(user, fe, gate)
self.validate_assignees(assignees, fe, gate)
Expand Down
2 changes: 1 addition & 1 deletion api/spec_mentors_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ def do_get(self, **kwargs):
[]).append(FeatureLink(id=feature.key.integer_id(), name=feature.name))

return [
SpecMentor(email, features).to_dict()
SpecMentor.model_construct(email=email, mentored_features=features).to_dict()
for email, features in sorted(mentors.items())
]
2 changes: 1 addition & 1 deletion client-src/elements/chromedash-admin-blink-page_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('chromedash-admin-blink-page', () => {
const response: ComponentsUsersResponse = {
users: [{id: 0, name: 'user0', email: 'user0@example.com'}],
components: [
{id: '0', name: 'component0', subscriber_ids: [0], owner_ids: [0]},
{id: 0, name: 'component0', subscriber_ids: [0], owner_ids: [0]},
],
};
csOpenApiClientStub = sinon.createStubInstance(DefaultApi);
Expand Down
1 change: 0 additions & 1 deletion framework/basehandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
from flask import session
from flask import render_template
from flask_cors import CORS
from gen.py.chromestatus_openapi.chromestatus_openapi.models.base_model import Model

# Our API responses are prefixed with this ro prevent attacks that
# exploit <script src="...">. See go/xssi.
Expand Down
16 changes: 11 additions & 5 deletions framework/basehandlers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

from gen.py.chromestatus_openapi.chromestatus_openapi.models.feature_links_response import FeatureLinksResponse
from gen.py.chromestatus_openapi.chromestatus_openapi.models.link_preview import LinkPreview
import testing_config # Must be imported before the module under test.

import json
Expand Down Expand Up @@ -456,15 +457,20 @@ def test_get__dict(self, mock_do_get):
def test_get__openapi_model(self, mock_do_get):
"""get() should return a JSON response if the do_get() return value is an
OpenAPI model."""
mock_do_get.return_value = FeatureLinksResponse(data='data',
has_stale_links=True)

mock_link_preview = LinkPreview.from_dict({'url': 'data', 'type': 'data'}).to_dict()

mock_do_get.return_value = FeatureLinksResponse(data=[mock_link_preview], has_stale_links=True)

with test_app.test_request_context('/path'):
response, _ = self.handler.get()
self.assertEqual(basehandlers.XSSI_PREFIX +
'{"data": "data", "has_stale_links": true}',
expected = basehandlers.XSSI_PREFIX + json.dumps({
"data": [mock_link_preview],
"has_stale_links": True
})
self.assertEqual(expected,
response.get_data().decode('utf-8'))


def test_post(self):
"""If a subclass has do_post(), post() should return a JSON response."""
self.handler = TestableAPIHandler()
Expand Down
1 change: 1 addition & 0 deletions gen/js/chromestatus-openapi/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ src/models/FeatureLinksResponse.ts
src/models/FeatureLinksSample.ts
src/models/FeatureLinksSummaryResponse.ts
src/models/FieldInfo.ts
src/models/FieldInfoValue.ts
src/models/Gate.ts
src/models/GateInfo.ts
src/models/GateLatency.ts
Expand Down
2 changes: 1 addition & 1 deletion gen/js/chromestatus-openapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"prepare": "npm run build"
},
"devDependencies": {
"typescript": "^5.6"
"typescript": "^4.0 || ^5.0"
}
}
16 changes: 8 additions & 8 deletions gen/js/chromestatus-openapi/src/models/FeatureLatency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ export interface FeatureLatency {
feature: FeatureLink;
/**
*
* @type {Date}
* @type {string}
* @memberof FeatureLatency
*/
entry_created_date: Date;
entry_created_date: string;
/**
*
* @type {number}
Expand All @@ -46,10 +46,10 @@ export interface FeatureLatency {
shipped_milestone: number;
/**
*
* @type {Date}
* @type {string}
* @memberof FeatureLatency
*/
shipped_date: Date;
shipped_date: string;
/**
*
* @type {Array<string>}
Expand Down Expand Up @@ -81,9 +81,9 @@ export function FeatureLatencyFromJSONTyped(json: any, ignoreDiscriminator: bool
return {

'feature': FeatureLinkFromJSON(json['feature']),
'entry_created_date': (new Date(json['entry_created_date'])),
'entry_created_date': json['entry_created_date'],
'shipped_milestone': json['shipped_milestone'],
'shipped_date': (new Date(json['shipped_date'])),
'shipped_date': json['shipped_date'],
'owner_emails': json['owner_emails'],
};
}
Expand All @@ -95,9 +95,9 @@ export function FeatureLatencyToJSON(value?: FeatureLatency | null): any {
return {

'feature': FeatureLinkToJSON(value['feature']),
'entry_created_date': ((value['entry_created_date']).toISOString().substring(0,10)),
'entry_created_date': value['entry_created_date'],
'shipped_milestone': value['shipped_milestone'],
'shipped_date': ((value['shipped_date']).toISOString().substring(0,10)),
'shipped_date': value['shipped_date'],
'owner_emails': value['owner_emails'],
};
}
Expand Down
15 changes: 11 additions & 4 deletions gen/js/chromestatus-openapi/src/models/FieldInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
*/

import { mapValues } from '../runtime';
import type { FieldInfoValue } from './FieldInfoValue';
import {
FieldInfoValueFromJSON,
FieldInfoValueFromJSONTyped,
FieldInfoValueToJSON,
} from './FieldInfoValue';

/**
*
* @export
Expand All @@ -27,10 +34,10 @@ export interface FieldInfo {
form_field_name?: string;
/**
*
* @type {object}
* @type {FieldInfoValue}
* @memberof FieldInfo
*/
value?: object;
value?: FieldInfoValue;
}

/**
Expand All @@ -51,7 +58,7 @@ export function FieldInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean):
return {

'form_field_name': json['form_field_name'] == null ? undefined : json['form_field_name'],
'value': json['value'] == null ? undefined : json['value'],
'value': json['value'] == null ? undefined : FieldInfoValueFromJSON(json['value']),
};
}

Expand All @@ -62,7 +69,7 @@ export function FieldInfoToJSON(value?: FieldInfo | null): any {
return {

'form_field_name': value['form_field_name'],
'value': value['value'],
'value': FieldInfoValueToJSON(value['value']),
};
}

42 changes: 42 additions & 0 deletions gen/js/chromestatus-openapi/src/models/FieldInfoValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* tslint:disable */
/* eslint-disable */
/**
* chomestatus API
* The API for chromestatus.com. chromestatus.com is the official tool used for tracking feature launches in Blink (the browser engine that powers Chrome and many other web browsers). This tool guides feature owners through our launch process and serves as a primary source for developer information that then ripples throughout the web developer ecosystem. More details at: https://github.com/GoogleChrome/chromium-dashboard
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

import { mapValues } from '../runtime';
/**
*
* @export
* @interface FieldInfoValue
*/
export interface FieldInfoValue {
}

/**
* Check if a given object implements the FieldInfoValue interface.
*/
export function instanceOfFieldInfoValue(value: object): value is FieldInfoValue {
return true;
}

export function FieldInfoValueFromJSON(json: any): FieldInfoValue {
return FieldInfoValueFromJSONTyped(json, false);
}

export function FieldInfoValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): FieldInfoValue {
return json;
}

export function FieldInfoValueToJSON(value?: FieldInfoValue | null): any {
return value;
}

4 changes: 2 additions & 2 deletions gen/js/chromestatus-openapi/src/models/Gate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ export function GateToJSON(value?: Gate | null): any {
'gate_name': value['gate_name'],
'escalation_email': value['escalation_email'],
'state': value['state'],
'requested_on': value['requested_on'] == null ? undefined : ((value['requested_on']).toISOString()),
'responded_on': value['responded_on'] == null ? undefined : ((value['responded_on']).toISOString()),
'requested_on': value['requested_on'] == null ? undefined : ((value['requested_on'] as any).toISOString()),
'responded_on': value['responded_on'] == null ? undefined : ((value['responded_on'] as any).toISOString()),
'assignee_emails': value['assignee_emails'],
'next_action': value['next_action'],
'additional_review': value['additional_review'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { mapValues } from '../runtime';
export interface OwnersAndSubscribersOfComponent {
/**
*
* @type {string}
* @type {number}
* @memberof OwnersAndSubscribersOfComponent
*/
id: string;
id: number;
/**
*
* @type {string}
Expand Down
Loading