2121use OCP \AppFramework \Http \DataResponse ;
2222use OCP \AppFramework \Http \RedirectResponse ;
2323use OCP \AppFramework \Http \TemplateResponse ;
24+ use OCP \AppFramework \Services \IAppConfig ;
2425use OCP \AppFramework \Services \IInitialState ;
2526use OCP \IConfig ;
2627use OCP \IL10N ;
3233
3334class ConfigController extends Controller {
3435
36+ /**
37+ * The switches of the admin settings, and whether each one is stored lazily.
38+ * dashboard_enabled and issue_notifications_enabled are read in Application::register(),
39+ * which runs on every request, so they stay non-lazy.
40+ */
41+ private const ADMIN_SWITCHES = [
42+ 'use_popup ' => true ,
43+ 'link_preview_enabled ' => true ,
44+ 'allow_default_link_token_to_anonymous ' => true ,
45+ 'allow_default_link_token_to_guests ' => true ,
46+ 'dashboard_enabled ' => false ,
47+ 'issue_notifications_enabled ' => false ,
48+ ];
49+
50+ private const SECRET_KEYS = ['client_id ' , 'client_secret ' , 'default_link_token ' ];
51+
3552 public function __construct (
3653 string $ appName ,
3754 IRequest $ request ,
3855 private IConfig $ config ,
56+ private IAppConfig $ appConfig ,
3957 private IURLGenerator $ urlGenerator ,
4058 private IL10N $ l ,
4159 private IInitialState $ initialStateService ,
@@ -108,13 +126,15 @@ public function setConfig(array $values): DataResponse {
108126 * @return DataResponse
109127 */
110128 public function setAdminConfig (array $ values ): DataResponse {
129+ // only the switches, so that a request cannot write a key the server owns, such as "enabled"
111130 foreach ($ values as $ key => $ value ) {
112- if (in_array ($ key , [ ' client_id ' , ' client_secret ' , ' default_link_token ' ], true )) {
131+ if (! array_key_exists ($ key , self :: ADMIN_SWITCHES ) || ! is_string ( $ value )) {
113132 return new DataResponse ([], Http::STATUS_BAD_REQUEST );
114- } else {
115- $ this ->config ->setAppValue (Application::APP_ID , $ key , $ value );
116133 }
117134 }
135+ foreach ($ values as $ key => $ value ) {
136+ $ this ->appConfig ->setAppValueString ($ key , $ value , lazy: self ::ADMIN_SWITCHES [$ key ]);
137+ }
118138 return new DataResponse ([]);
119139 }
120140
@@ -127,14 +147,15 @@ public function setAdminConfig(array $values): DataResponse {
127147 #[PasswordConfirmationRequired]
128148 public function setSensitiveAdminConfig (array $ values ): DataResponse {
129149 foreach ($ values as $ key => $ value ) {
130- if (in_array ($ key , ['client_id ' , 'client_secret ' , 'default_link_token ' ], true )) {
131- $ this ->secretService ->setEncryptedAppValue ($ key , $ value );
132- if ($ key === 'default_link_token ' ) {
133- $ info = $ this ->githubAPIService ->updateLinkTokenUserInfo ($ value );
134- return new DataResponse ($ info );
135- }
136- } else {
137- $ this ->config ->setAppValue (Application::APP_ID , $ key , $ value );
150+ if (!in_array ($ key , self ::SECRET_KEYS , true ) || !is_string ($ value )) {
151+ return new DataResponse ([], Http::STATUS_BAD_REQUEST );
152+ }
153+ }
154+ foreach ($ values as $ key => $ value ) {
155+ $ this ->secretService ->setEncryptedAppValue ($ key , $ value );
156+ if ($ key === 'default_link_token ' ) {
157+ $ info = $ this ->githubAPIService ->updateLinkTokenUserInfo ($ value );
158+ return new DataResponse ($ info );
138159 }
139160 }
140161 return new DataResponse ([]);
@@ -184,7 +205,7 @@ public function oauthRedirect(string $code, string $state): RedirectResponse {
184205 $ this ->config ->setUserValue ($ this ->userId , Application::APP_ID , 'token_type ' , 'oauth ' );
185206 $ userInfo = $ this ->storeUserInfo ();
186207
187- $ usePopup = $ this ->config -> getAppValue (Application:: APP_ID , 'use_popup ' , '0 ' ) === '1 ' ;
208+ $ usePopup = $ this ->appConfig -> getAppValueString ( 'use_popup ' , '0 ' , lazy: true ) === '1 ' ;
188209 if ($ usePopup ) {
189210 return new RedirectResponse (
190211 $ this ->urlGenerator ->linkToRoute ('integration_github.config.popupSuccessPage ' , [
0 commit comments