/*
 * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.keycloak.testsuite.offlineconfig;

import org.junit.After;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.offlineconfig.AdminRecovery;
import org.keycloak.offlineconfig.OfflineConfigException;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebRule;

/**
 * Test the AdminRecovery class.
 *
 * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
 */
public class AdminRecoveryTest {
    @ClassRule
    public static KeycloakRule keycloakRule = new KeycloakRule();

    @Rule
    public WebRule webRule = new WebRule(this);

    // Verifies that system properties were cleared at the end of recovery
    @After
    public void verifySysPropsCleared() {
        Assert.assertNull(System.getProperty(AdminRecovery.RECOVER_ADMIN_ACCOUNT));
        Assert.assertNull(System.getProperty(AdminRecovery.TEMP_ADMIN_PASSWORD));
    }

    @Test
    public void testAdminDeletedRecovery() {
        KeycloakSession session = keycloakRule.startSession();
        RealmModel masterRealm = session.realms().getRealmByName("master");
        UserModel adminUser = session.users().getUserByUsername("admin", masterRealm);
        session.users().removeUser(masterRealm, adminUser);
        adminUser = session.users().getUserByUsername("admin", masterRealm);
        keycloakRule.stopSession(session, true);

        Assert.assertNull(adminUser);

        doAdminRecovery(session);

        session = keycloakRule.startSession();
        adminUser = session.users().getUserByUsername("admin", masterRealm);
        Assert.assertNotNull(adminUser);
        Assert.assertTrue(adminUser.getRequiredActions().contains(RequiredAction.UPDATE_PASSWORD.toString()));
    }

    @Test
    public void testAdminPasswordRecovery() {
        KeycloakSession session = keycloakRule.startSession();
        RealmModel masterRealm = session.realms().getRealmByName("master");
        UserModel adminUser = session.users().getUserByUsername("admin", masterRealm);
        UserCredentialValueModel password = adminUser.getCredentialsDirectly().get(0);
        password.setValue("forgotten-password");
        adminUser.updateCredentialDirectly(password);
        keycloakRule.stopSession(session, true);

        Assert.assertEquals("forgotten-password", getAdminPassword());

        doAdminRecovery(session);

        Assert.assertNotEquals("forgotten-password", getAdminPassword());
    }

    @Test(expected = OfflineConfigException.class)
    public void testAdminRecoveryWithoutPassword() {
        KeycloakSession session = keycloakRule.startSession();
        System.setProperty(AdminRecovery.RECOVER_ADMIN_ACCOUNT, "true");
        AdminRecovery.recover(session.getKeycloakSessionFactory());
    }

    private void doAdminRecovery(KeycloakSession session) {
        System.setProperty(AdminRecovery.RECOVER_ADMIN_ACCOUNT, "true");
        System.setProperty(AdminRecovery.TEMP_ADMIN_PASSWORD, "foo");
        AdminRecovery.recover(session.getKeycloakSessionFactory());
    }

    private String getAdminPassword() {
        KeycloakSession session = keycloakRule.startSession();
        RealmModel masterRealm = session.realms().getRealmByName("master");
        UserModel adminUser = session.users().getUserByUsername("admin", masterRealm);
        UserCredentialValueModel password = adminUser.getCredentialsDirectly().get(0);
        keycloakRule.stopSession(session, true);
        return password.getValue();
    }
}

@@ -938,24 +938,72 @@
 RealmModel;%0A
+import org.keycloak.models.UserCredentialModel;%0A
 import org.k
@@ -1039,24 +1039,24 @@
 ValueModel;%0A
-
 import org.k
@@ -1237,24 +1237,76 @@
 gException;%0A
+import org.keycloak.services.managers.RealmManager;%0A
 import org.k
@@ -1541,24 +1541,24 @@
  @ClassRule%0A
-
     public s
@@ -1609,16 +1609,788 @@
 akRule()
+ %7B%0A%0A        @Override%0A        protected void after() %7B%0A%0A            // Need to reset admin user to default password and remove required action to not break next tests%0A            update(new KeycloakSetup() %7B%0A%0A                @Override%0A                public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) %7B%0A                    UserModel adminUser = session.users().getUserByUsername(%22admin%22, adminstrationRealm);%0A                    UserCredentialModel password = UserCredentialModel.password(%22admin%22);%0A                    adminUser.updateCredential(password);%0A%0A                    adminUser.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);%0A                %7D%0A            %7D);%0A%0A            super.after();%0A        %7D%0A    %7D
 ;%0A%0A    @

Fix AdminRecoveryTest to not break admin tests