@@ -84,6 +84,33 @@ const getResourceFromScope = (scope: Scope): Resource | undefined => {
8484 return undefined ;
8585} ;
8686
87+ /**
88+ * We need to map the API response errors to the actual form fields.
89+ * We do this by pulling out scopes and mapping each scope error to the correct input.
90+ * @param {Object } responseJSON
91+ */
92+ const mapFormErrors = ( responseJSON ?: any ) => {
93+ if ( ! responseJSON ) {
94+ return responseJSON ;
95+ }
96+ const formErrors = omit ( responseJSON , [ 'scopes' ] ) ;
97+ if ( responseJSON . scopes ) {
98+ responseJSON . scopes . forEach ( ( message : string ) => {
99+ // find the scope from the error message of a specific format
100+ const matches = message . match ( / R e q u e s t e d p e r m i s s i o n o f ( \w + : \w + ) / ) ;
101+ if ( matches ) {
102+ const scope = matches [ 1 ] ;
103+ const resource = getResourceFromScope ( scope as Scope ) ;
104+ // should always match but technically resource can be undefined
105+ if ( resource ) {
106+ formErrors [ `${ resource } --permission` ] = [ message ] ;
107+ }
108+ }
109+ } ) ;
110+ }
111+ return formErrors ;
112+ } ;
113+
87114class SentryAppFormModel extends FormModel {
88115 /**
89116 * Filter out Permission input field values.
@@ -106,33 +133,6 @@ class SentryAppFormModel extends FormModel {
106133 return data ;
107134 } , { } ) ;
108135 }
109-
110- /**
111- * We need to map the API response errors to the actual form fields.
112- * We do this by pulling out scopes and mapping each scope error to the correct input.
113- * @param {Object } responseJSON
114- */
115- mapFormErrors ( responseJSON ?: any ) {
116- if ( ! responseJSON ) {
117- return responseJSON ;
118- }
119- const formErrors = omit ( responseJSON , [ 'scopes' ] ) ;
120- if ( responseJSON . scopes ) {
121- responseJSON . scopes . forEach ( ( message : string ) => {
122- // find the scope from the error message of a specific format
123- const matches = message . match ( / R e q u e s t e d p e r m i s s i o n o f ( \w + : \w + ) / ) ;
124- if ( matches ) {
125- const scope = matches [ 1 ] ;
126- const resource = getResourceFromScope ( scope as Scope ) ;
127- // should always match but technically resource can be undefined
128- if ( resource ) {
129- formErrors [ `${ resource } --permission` ] = [ message ] ;
130- }
131- }
132- } ) ;
133- }
134- return formErrors ;
135- }
136136}
137137
138138type Props = RouteComponentProps < { appSlug ?: string } , { } > & {
@@ -145,7 +145,7 @@ type State = AsyncView['state'] & {
145145} ;
146146
147147class SentryApplicationDetails extends AsyncView < Props , State > {
148- form = new SentryAppFormModel ( ) ;
148+ form = new SentryAppFormModel ( { mapFormErrors } ) ;
149149
150150 getDefaultState ( ) : State {
151151 return {
0 commit comments