4848use OCP \App \AppPathNotFoundException ;
4949use OCP \App \IAppManager ;
5050use OCP \AppFramework \Controller ;
51+ use OCP \AppFramework \Http \Attribute \AuthorizedAdminSetting ;
52+ use OCP \AppFramework \Http \Attribute \NoAdminRequired ;
53+ use OCP \AppFramework \Http \Attribute \NoCSRFRequired ;
54+ use OCP \AppFramework \Http \Attribute \PublicPage ;
55+ use OCP \AppFramework \Http \Attribute \StrictCookiesRequired ;
56+ use OCP \AppFramework \Http \Attribute \SubAdminRequired ;
5157use OCP \AppFramework \Http \JSONResponse ;
5258use OCP \AppFramework \Http \RedirectResponse ;
5359use OCP \AppFramework \Http \Response ;
6167use OCP \IUserSession ;
6268use OCP \Util ;
6369use Psr \Log \LoggerInterface ;
70+ use ReflectionMethod ;
6471
6572/**
6673 * Used to do all the authentication and checking stuff for a controller method
@@ -145,22 +152,24 @@ public function beforeController($controller, $methodName) {
145152 $ this ->navigationManager ->setActiveEntry ('spreed ' );
146153 }
147154
155+ $ reflectionMethod = new ReflectionMethod ($ controller , $ methodName );
156+
148157 // security checks
149- $ isPublicPage = $ this ->reflector -> hasAnnotation ( 'PublicPage ' );
158+ $ isPublicPage = $ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'PublicPage ' , PublicPage::class );
150159 if (!$ isPublicPage ) {
151160 if (!$ this ->isLoggedIn ) {
152161 throw new NotLoggedInException ();
153162 }
154163 $ authorized = false ;
155- if ($ this ->reflector -> hasAnnotation ( 'AuthorizedAdminSetting ' )) {
164+ if ($ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'AuthorizedAdminSetting ' , AuthorizedAdminSetting::class )) {
156165 $ authorized = $ this ->isAdminUser ;
157166
158- if (!$ authorized && $ this ->reflector -> hasAnnotation ( 'SubAdminRequired ' )) {
167+ if (!$ authorized && $ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'SubAdminRequired ' , SubAdminRequired::class )) {
159168 $ authorized = $ this ->isSubAdmin ;
160169 }
161170
162171 if (!$ authorized ) {
163- $ settingClasses = explode ( ' ; ' , $ this ->reflector -> getAnnotationParameter ( ' AuthorizedAdminSetting ' , ' settings ' ) );
172+ $ settingClasses = $ this ->getAuthorizedAdminSettingClasses ( $ reflectionMethod );
164173 $ authorizedClasses = $ this ->groupAuthorizationMapper ->findAllClassesForUser ($ this ->userSession ->getUser ());
165174 foreach ($ settingClasses as $ settingClass ) {
166175 $ authorized = in_array ($ settingClass , $ authorizedClasses , true );
@@ -174,29 +183,30 @@ public function beforeController($controller, $methodName) {
174183 throw new NotAdminException ($ this ->l10n ->t ('Logged in user must be an admin, a sub admin or gotten special right to access this setting ' ));
175184 }
176185 }
177- if ($ this ->reflector -> hasAnnotation ( 'SubAdminRequired ' )
186+ if ($ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'SubAdminRequired ' , SubAdminRequired::class )
178187 && !$ this ->isSubAdmin
179188 && !$ this ->isAdminUser
180189 && !$ authorized ) {
181190 throw new NotAdminException ($ this ->l10n ->t ('Logged in user must be an admin or sub admin ' ));
182191 }
183- if (!$ this ->reflector -> hasAnnotation ( 'SubAdminRequired ' )
184- && !$ this ->reflector -> hasAnnotation ( 'NoAdminRequired ' )
192+ if (!$ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'SubAdminRequired ' , SubAdminRequired::class )
193+ && !$ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'NoAdminRequired ' , NoAdminRequired::class )
185194 && !$ this ->isAdminUser
186195 && !$ authorized ) {
187196 throw new NotAdminException ($ this ->l10n ->t ('Logged in user must be an admin ' ));
188197 }
189198 }
190199
191200 // Check for strict cookie requirement
192- if ($ this ->reflector ->hasAnnotation ('StrictCookieRequired ' ) || !$ this ->reflector ->hasAnnotation ('NoCSRFRequired ' )) {
201+ if ($ this ->hasAnnotationOrAttribute ($ reflectionMethod , 'StrictCookieRequired ' , StrictCookiesRequired::class) ||
202+ !$ this ->hasAnnotationOrAttribute ($ reflectionMethod , 'NoCSRFRequired ' , NoCSRFRequired::class)) {
193203 if (!$ this ->request ->passesStrictCookieCheck ()) {
194204 throw new StrictCookieMissingException ();
195205 }
196206 }
197207 // CSRF check - also registers the CSRF token since the session may be closed later
198208 Util::callRegister ();
199- if (!$ this ->reflector -> hasAnnotation ( 'NoCSRFRequired ' )) {
209+ if (!$ this ->hasAnnotationOrAttribute ( $ reflectionMethod , 'NoCSRFRequired ' , NoCSRFRequired::class )) {
200210 /*
201211 * Only allow the CSRF check to fail on OCS Requests. This kind of
202212 * hacks around that we have no full token auth in place yet and we
@@ -232,6 +242,48 @@ public function beforeController($controller, $methodName) {
232242 }
233243 }
234244
245+ /**
246+ * @template T
247+ *
248+ * @param ReflectionMethod $reflectionMethod
249+ * @param string $annotationName
250+ * @param class-string<T> $attributeClass
251+ * @return boolean
252+ */
253+ protected function hasAnnotationOrAttribute (ReflectionMethod $ reflectionMethod , string $ annotationName , string $ attributeClass ): bool {
254+ if (!empty ($ reflectionMethod ->getAttributes ($ attributeClass ))) {
255+ return true ;
256+ }
257+
258+ if ($ this ->reflector ->hasAnnotation ($ annotationName )) {
259+ return true ;
260+ }
261+
262+ return false ;
263+ }
264+
265+ /**
266+ * @param ReflectionMethod $reflectionMethod
267+ * @return string[]
268+ */
269+ protected function getAuthorizedAdminSettingClasses (ReflectionMethod $ reflectionMethod ): array {
270+ $ classes = [];
271+ if ($ this ->reflector ->hasAnnotation ('AuthorizedAdminSetting ' )) {
272+ $ classes = explode ('; ' , $ this ->reflector ->getAnnotationParameter ('AuthorizedAdminSetting ' , 'settings ' ));
273+ }
274+
275+ $ attributes = $ reflectionMethod ->getAttributes (AuthorizedAdminSetting::class);
276+ if (!empty ($ attributes )) {
277+ foreach ($ attributes as $ attribute ) {
278+ /** @var AuthorizedAdminSetting $setting */
279+ $ setting = $ attribute ->newInstance ();
280+ $ classes [] = $ setting ->getSettings ();
281+ }
282+ }
283+
284+ return $ classes ;
285+ }
286+
235287 /**
236288 * If an SecurityException is being caught, ajax requests return a JSON error
237289 * response and non ajax requests redirect to the index
0 commit comments