• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

opensrp / opensrp-client-core / #175

pending completion
#175

push

github-actions

web-flow
Merge pull request #921 from opensrp/refactor-user-settings-task

Refactor user settings task

18309 of 26768 relevant lines covered (68.4%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.27
opensrp-core/src/main/java/org/smartregister/CoreLibrary.java
1
package org.smartregister;
2

3
import static androidx.preference.PreferenceManager.getDefaultSharedPreferences;
4

5
import android.accounts.Account;
6
import android.accounts.AccountManager;
7
import android.accounts.OnAccountsUpdateListener;
8
import android.content.Intent;
9
import android.content.SharedPreferences;
10
import android.text.TextUtils;
11

12
import androidx.annotation.Nullable;
13
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
14

15
import org.apache.commons.lang3.StringUtils;
16
import org.smartregister.account.AccountAuthenticatorXml;
17
import org.smartregister.authorizer.P2PSyncAuthorizationService;
18
import org.smartregister.p2p.P2PLibrary;
19
import org.smartregister.pathevaluator.PathEvaluatorLibrary;
20
import org.smartregister.repository.AllSharedPreferences;
21
import org.smartregister.repository.P2PReceiverTransferDao;
22
import org.smartregister.repository.P2PSenderTransferDao;
23
import org.smartregister.repository.TaskNotesRepository;
24
import org.smartregister.repository.dao.ClientDaoImpl;
25
import org.smartregister.repository.dao.EventDaoImpl;
26
import org.smartregister.repository.dao.LocationDaoImpl;
27
import org.smartregister.repository.dao.TaskDaoImpl;
28
import org.smartregister.sync.P2PSyncFinishCallback;
29
import org.smartregister.util.CredentialsHelper;
30
import org.smartregister.util.Utils;
31

32
import java.util.Map;
33
import java.util.Set;
34

35
import timber.log.Timber;
36

37
/**
38
 * Created by keyman on 31/07/17.
39
 */
40
public class CoreLibrary implements OnAccountsUpdateListener {
41

42
    private static CoreLibrary instance;
43
    private static long buildTimeStamp;
44
    private static String ENCRYPTED_PREFS_KEY_KEYSET = "__androidx_security_crypto_encrypted_prefs_key_keyset__";
1✔
45
    private static String ENCRYPTED_PREFS_VALUE_KEYSET = "__androidx_security_crypto_encrypted_prefs_value_keyset__";
1✔
46
    private final Context context;
47
    private final SyncConfiguration syncConfiguration;
48
    private boolean isPeerToPeerProcessing = false;
1✔
49
    private String ecClientFieldsFile = "ec_client_fields.json";
1✔
50
    private P2POptions p2POptions;
51
    private AccountManager accountManager;
52
    private AccountAuthenticatorXml authenticatorXml;
53

54
    protected CoreLibrary(Context contextArg, SyncConfiguration syncConfiguration, @Nullable P2POptions p2POptions) {
1✔
55
        context = contextArg;
1✔
56
        this.syncConfiguration = syncConfiguration;
1✔
57
        this.p2POptions = p2POptions;
1✔
58

59
        initP2pLibrary(null);
1✔
60
        if (syncConfiguration != null && syncConfiguration.runPlanEvaluationOnClientProcessing()) {
1✔
61
            PathEvaluatorLibrary.init(new LocationDaoImpl(), new ClientDaoImpl(), new TaskDaoImpl(new TaskNotesRepository()), new EventDaoImpl());
1✔
62
        }
63
    }
1✔
64

65
    public static void init(Context context) {
66
        init(context, null);
1✔
67
    }
1✔
68

69
    public static void init(Context context, SyncConfiguration syncConfiguration) {
70
        init(context, syncConfiguration, BuildConfig.BUILD_TIMESTAMP);
1✔
71
    }
1✔
72

73
    public static void init(Context context, SyncConfiguration syncConfiguration, long buildTimestamp) {
74
        init(context, syncConfiguration, buildTimestamp, null);
1✔
75
    }
1✔
76

77
    public static void init(Context context, SyncConfiguration syncConfiguration, long buildTimestamp, @Nullable P2POptions options) {
78
        if (instance == null) {
1✔
79
            instance = new CoreLibrary(context, syncConfiguration, options);
1✔
80
            buildTimeStamp = buildTimestamp;
1✔
81
            upgradeSharedPreferences();
1✔
82
            checkPlatformMigrations();
1✔
83
        }
84
    }
1✔
85

86
    public static void destroyInstance() {
87
        instance = null;
1✔
88
    }
1✔
89

90
    private static void checkPlatformMigrations() {
91
        boolean shouldMigrate = CredentialsHelper.shouldMigrate();
1✔
92
        if (shouldMigrate && StringUtils.isNotBlank(instance.context().userService().getAllSharedPreferences().fetchPioneerUser())) {//Force remote login
1✔
93
            Utils.logoutUser(instance.context(), instance.context().applicationContext().getString(R.string.new_db_encryption_version_migration));
1✔
94
        }
95
        instance.context().userService().getAllSharedPreferences().migratePassphrase();
1✔
96
    }
1✔
97

98
    /**
99
     * Check encrypted prefs sync configuration
100
     * If configured to encrypt and there are previously saved shared prefs, recreate them encrypted
101
     * If configured not to encrypt but previous version encrypted, clear the prefs
102
     */
103
    private static void upgradeSharedPreferences() {
104
        try {
105
            android.content.Context appContext = instance.context().applicationContext();
1✔
106
            SharedPreferences existingPrefs = appContext.getSharedPreferences(appContext.getPackageName() + "_preferences", android.content.Context.MODE_PRIVATE);
1✔
107
            Map<String, ?> entries = existingPrefs.getAll();
1✔
108

109
            // check the version of SharedPreferences (encrypted vs unencrypted)
110
            // as well as whether encryption key-value pair is set
111
            if (Utils.getBooleanProperty(AllConstants.PROPERTY.ENCRYPT_SHARED_PREFERENCES)
1✔
112
                    && !entries.containsKey(ENCRYPTED_PREFS_KEY_KEYSET)
1✔
113
                    && !entries.containsKey(ENCRYPTED_PREFS_VALUE_KEYSET)) {
1✔
114

115
                existingPrefs.edit().clear().apply();
1✔
116

117
                // create the new instance
118
                SharedPreferences newPrefs = instance.context().allSharedPreferences().getPreferences();
1✔
119

120
                copySharedPreferences(entries, newPrefs);
1✔
121
            }
122
        } catch (Exception e) {
×
123
            Timber.e(e);
×
124
        }
1✔
125
    }
1✔
126

127
    private static void copySharedPreferences(Map<String, ?> entries, SharedPreferences preferences) {
128
        try {
129
            for (Map.Entry<String, ?> entry : entries.entrySet()) {
1✔
130
                if (entry.getValue() instanceof Boolean) {
1✔
131
                    preferences.edit().putBoolean(entry.getKey(), (Boolean) entry.getValue()).apply();
1✔
132
                } else if (entry.getValue() instanceof Float) {
1✔
133
                    preferences.edit().putFloat(entry.getKey(), (Float) entry.getValue()).apply();
1✔
134
                } else if (entry.getValue() instanceof Integer) {
1✔
135
                    preferences.edit().putInt(entry.getKey(), (Integer) entry.getValue()).apply();
1✔
136
                } else if (entry.getValue() instanceof Long) {
1✔
137
                    preferences.edit().putLong(entry.getKey(), (Long) entry.getValue()).apply();
1✔
138
                } else if (entry.getValue() instanceof String) {
1✔
139
                    preferences.edit().putString(entry.getKey(), (String) entry.getValue()).apply();
1✔
140
                } else if (entry.getValue() instanceof Set) {
1✔
141
                    preferences.edit().putStringSet(entry.getKey(), (Set) entry.getValue()).apply();
1✔
142
                }
143
            }
1✔
144
        } catch (Exception e) {
1✔
145
            Timber.e(e, "Failed to save SharedPreference");
1✔
146
        }
1✔
147
    }
1✔
148

149
    public static CoreLibrary getInstance() {
150
        if (instance == null) {
1✔
151
            throw new IllegalStateException(" Instance does not exist!!! Call "
1✔
152
                    + CoreLibrary.class.getName()
1✔
153
                    + ".init method in the onCreate method of "
154
                    + "your Application class ");
155
        }
156
        return instance;
1✔
157
    }
158

159
    /**
160
     * Use this method when testing.
161
     * It should replace org.smartregister.Context#setInstance(org.smartregister.Context) which has been removed
162
     *
163
     * @param context
164
     */
165
    public static void reset(Context context) {
166
        if (context != null) {
1✔
167
            instance = new CoreLibrary(context, null, null);
1✔
168
        }
169
    }
1✔
170

171
    public static void reset(Context context, SyncConfiguration syncConfiguration) {
172
        if (context != null) {
1✔
173
            instance = new CoreLibrary(context, syncConfiguration, null);
1✔
174
        }
175
    }
1✔
176

177
    public static long getBuildTimeStamp() {
178
        return buildTimeStamp;
1✔
179
    }
180

181
    public static boolean isTimecheckDisabled() {
182
        return AllConstants.TIME_CHECK;
×
183
    }
184

185
    public void initP2pLibrary(@Nullable String username) {
186
        if (p2POptions != null && p2POptions.isEnableP2PLibrary()) {
1✔
187
            String p2pUsername = username;
1✔
188
            AllSharedPreferences allSharedPreferences = new AllSharedPreferences(getDefaultSharedPreferences(context.applicationContext()));
1✔
189
            if (p2pUsername == null) {
1✔
190
                p2pUsername = allSharedPreferences.fetchRegisteredANM();
1✔
191
            }
192

193
            if (!TextUtils.isEmpty(p2pUsername)) {
1✔
194
                String teamId = allSharedPreferences.fetchDefaultTeamId(p2pUsername);
1✔
195

196
                if (p2POptions.getAuthorizationService() == null) {
1✔
197
                    p2POptions.setAuthorizationService(new P2PSyncAuthorizationService(teamId));
1✔
198
                }
199

200
                if (p2POptions.getReceiverTransferDao() == null) {
1✔
201
                    p2POptions.setReceiverTransferDao(new P2PReceiverTransferDao());
1✔
202
                }
203

204
                if (p2POptions.getSenderTransferDao() == null) {
1✔
205
                    p2POptions.setSenderTransferDao(new P2PSenderTransferDao());
1✔
206
                }
207

208
                if (p2POptions.getSyncFinishedCallback() == null) {
1✔
209
                    p2POptions.setSyncFinishedCallback(new P2PSyncFinishCallback());
1✔
210
                }
211

212
                P2PLibrary.Options options = new P2PLibrary.Options(context.applicationContext()
1✔
213
                        , teamId, p2pUsername, p2POptions.getAuthorizationService(), p2POptions.getReceiverTransferDao()
1✔
214
                        , p2POptions.getSenderTransferDao());
1✔
215
                options.setBatchSize(p2POptions.getBatchSize());
1✔
216
                options.setSyncFinishedCallback(p2POptions.getSyncFinishedCallback());
1✔
217
                options.setRecalledIdentifier(p2POptions.getRecalledIdentifier());
1✔
218

219
                P2PLibrary.init(options);
1✔
220
            }
221
        }
222
    }
1✔
223

224
    public Context context() {
225
        return context;
1✔
226
    }
227

228
    @Nullable
229
    public SyncConfiguration getSyncConfiguration() {
230
        return syncConfiguration;
1✔
231
    }
232

233
    public AccountManager getAccountManager() {
234
        if (accountManager == null) {
1✔
235
            accountManager = AccountManager.get(context.applicationContext());
1✔
236
            accountManager.addOnAccountsUpdatedListener(this, null, true);
1✔
237
        }
238

239
        return accountManager;
1✔
240
    }
241

242
    public AccountAuthenticatorXml getAccountAuthenticatorXml() {
243
        if (authenticatorXml == null)
1✔
244
            authenticatorXml = Utils.parseAuthenticatorXMLConfigData(context.applicationContext());
1✔
245

246
        return authenticatorXml;
1✔
247
    }
248

249
    public String getEcClientFieldsFile() {
250
        return ecClientFieldsFile;
1✔
251
    }
252

253
    public void setEcClientFieldsFile(String ecClientFieldsFile) {
254
        this.ecClientFieldsFile = ecClientFieldsFile;
1✔
255
    }
1✔
256

257
    @Nullable
258
    public P2POptions getP2POptions() {
259
        return p2POptions;
1✔
260
    }
261

262
    public boolean isPeerToPeerProcessing() {
263
        return isPeerToPeerProcessing;
1✔
264
    }
265

266
    public void setPeerToPeerProcessing(boolean peerToPeerProcessing) {
267
        isPeerToPeerProcessing = peerToPeerProcessing;
1✔
268

269
        sendPeerToPeerProcessingStatus(isPeerToPeerProcessing);
1✔
270
    }
1✔
271

272
    private void sendPeerToPeerProcessingStatus(boolean status) {
273
        Intent intent = new Intent();
1✔
274
        intent.setAction(AllConstants.PeerToPeer.PROCESSING_ACTION);
1✔
275
        intent.putExtra(AllConstants.PeerToPeer.KEY_IS_PROCESSING, status);
1✔
276

277
        LocalBroadcastManager.getInstance(context.applicationContext())
1✔
278
                .sendBroadcast(intent);
1✔
279
    }
1✔
280

281
    @Override
282
    public void onAccountsUpdated(Account[] accounts) {
283
        if (context.allSharedPreferences().getDBEncryptionVersion() > 0) {
1✔
284
            try {
285
                String loggedInUser = context.allSharedPreferences().fetchRegisteredANM();
1✔
286

287
                if (!StringUtils.isBlank(loggedInUser)) {
1✔
288

289
                    boolean accountExists = false;
1✔
290

291
                    for (Account account : accounts) {
1✔
292
                        if (account.type.equals(getAccountAuthenticatorXml().getAccountType()) && account.name.equals(context.allSharedPreferences().fetchRegisteredANM())) {
1✔
293
                            accountExists = true;
1✔
294
                            break;
1✔
295
                        }
296
                    }
297

298
                    if (!accountExists) {
1✔
299

300
                        Utils.logoutUser(context, context.applicationContext().getString(R.string.account_removed));
1✔
301

302
                    }
303
                }
304
            } catch (Exception e) {
×
305
                Timber.e(e);
×
306
            }
1✔
307
        }
308
    }
1✔
309
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc