use of co.krypt.krypton.protocol.Profile in project krypton-android by kryptco.
the class MeFragment method updateUI.
@Subscribe(threadMode = ThreadMode.MAIN)
public void updateUI(IdentityService.GetProfileResult r) {
Profile me = r.profile;
if (me != null) {
profileEmail.setText(me.email);
profileEmail.setTextColor(getResources().getColor(R.color.appBlack, null));
shareButton.setOnClickListener(v -> {
if (me != null) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, me.shareText());
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share your Krypton SSH Public Key"));
}
});
} else {
Log.e(TAG, "no profile");
}
}
use of co.krypt.krypton.protocol.Profile in project krypton-android by kryptco.
the class MeStorage method loadWithUserID.
public Profile loadWithUserID(@Nullable UserID userID) {
synchronized (lock) {
String meJSON = preferences.getString("ME", null);
if (meJSON == null) {
Log.i(TAG, "no profile found");
return null;
}
Profile me = JSON.fromJson(meJSON, Profile.class);
if (me == null) {
Log.i(TAG, "no profile found");
return null;
}
try {
SSHKeyPairI kp = getOrLoadKeyPair(context);
if (kp != null) {
me.sshWirePublicKey = kp.publicKeySSHWireFormat();
if (userID != null) {
try {
List<UserID> userIDs = getUserIDs();
// keep USER_ID_LIMIT most recent UserIDs
if (userIDs.remove(userID)) {
userIDs.add(userID);
} else {
if (userIDs.size() >= USER_ID_LIMIT) {
userIDs.remove(0);
}
userIDs.add(userID);
PGPPublicKey pgpPublicKey = PGPManager.publicKeyWithIdentities(kp, userIDs);
me.pgpPublicKey = pgpPublicKey.serializedBytes();
if (userIDs.size() == USER_ID_LIMIT) {
// detect abuse of exporting PGP userIDs
Notifications.notifyPGPKeyExport(context, pgpPublicKey);
}
}
set(me, userIDs);
} catch (PGPException | IOException e) {
e.printStackTrace();
}
}
}
} catch (InvalidKeyException | IOException | CryptoException e) {
e.printStackTrace();
}
try {
me.teamCheckpoint = TeamDataProvider.getTeamCheckpoint(context).success;
} catch (Native.NotLinked notLinked) {
notLinked.printStackTrace();
}
return me;
}
}
use of co.krypt.krypton.protocol.Profile in project krypton-android by kryptco.
the class MemberQR method onCreateView.
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.fragment_teams_invite_inperson_member_qr, container, false);
qrPayloads.set(null);
qr = v.findViewById(R.id.memberQRCode);
AppCompatButton cancelButton = v.findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(v_ -> {
Transitions.beginFade(this).remove(this).commitAllowingStateLoss();
});
loadQRProgress = v.findViewById(R.id.loadQRProgressBar);
joinProgress = v.findViewById(R.id.memberJoinProgress);
joinProgress.setAlpha(0);
Sigchain.AdminQRPayload adminQRPayload = MemberScan.lastScannedPayload.get();
if (adminQRPayload == null) {
getFragmentManager().popBackStackImmediate();
} else {
new Thread(() -> {
Profile p = new MeStorage(getContext()).load();
if (p == null) {
Error.shortToast(getContext(), "Error loading profile, first generate your Krypton SSH key");
} else {
EventBus.getDefault().register(this);
EventBus.getDefault().post(new TeamService.GenerateClient(C.background(getContext()), new Sigchain.GenerateClientInput(p, adminQRPayload.teamPublicKey, adminQRPayload.lastBlockHash)));
}
}).start();
}
return v;
}
use of co.krypt.krypton.protocol.Profile in project krypton-android by kryptco.
the class OnboardingVerifyEmailFragment method onCreateView.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_teams_onboarding_verify_email, container, false);
Button cancelButton = rootView.findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(v -> {
progress.reset();
getActivity().finish();
});
ProgressBar progressBar = rootView.findViewById(R.id.progressBar);
progressBar.setAlpha(0);
Button changeButton = rootView.findViewById(R.id.changeButton);
changeButton.setEnabled(false);
Button resendButton = rootView.findViewById(R.id.resendButton);
resendButton.setEnabled(false);
ConstraintLayout checkYourEmailContainer = rootView.findViewById(R.id.checkYourEmailContainer);
checkYourEmailContainer.setAlpha(0);
AppCompatTextView teamName = rootView.findViewById(R.id.teamName);
teamName.setText(progress.getTeamOnboardingData().name);
emailEditText = rootView.findViewById(R.id.profileEmail);
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
Runnable focusEmail = () -> {
emailEditText.setEnabled(true);
emailEditText.requestFocus();
if (imm != null) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
progressBar.animate().alpha(0).setDuration(500).start();
};
focusEmail.run();
Runnable requestEmailChallenge = () -> {
emailEditText.setEnabled(false);
emailEditText.clearFocus();
if (imm != null) {
imm.hideSoftInputFromWindow(emailEditText.getWindowToken(), 0);
}
progressBar.animate().alpha(1).setDuration(1000).start();
final String email = emailEditText.getEditableText().toString();
new Thread(() -> {
MeStorage meStorage = Silo.shared(getContext()).meStorage();
try {
meStorage.setEmail(email);
} catch (CryptoException e) {
Error.shortToast(getContext(), "Failed to set email: " + e.getMessage());
e.printStackTrace();
return;
}
Profile me = meStorage.load();
progress.updateTeamData((s, d) -> {
if (s.equals(CreateStage.VERIFY_EMAIL) || s.equals(CreateStage.EMAIL_CHALLENGE_SENT)) {
d.creatorProfile = me;
Log.i(TAG, "requesting email challenge...");
try {
final Sigchain.NativeResult<JsonObject> result = TeamDataProvider.requestEmailChallenge(getContext(), email);
emailEditText.post(() -> {
if (result.success != null) {
Log.i(TAG, "request email challenge success");
progressBar.animate().alpha(0).setDuration(500).start();
checkYourEmailContainer.animate().alpha(1).setDuration(1000).start();
changeButton.setEnabled(true);
resendButton.setEnabled(true);
} else {
Log.i(TAG, "request email challenge failure: " + result.error);
Error.shortToast(getContext(), "Error sending email: " + result.error);
focusEmail.run();
}
});
if (result.success != null) {
return CreateStage.EMAIL_CHALLENGE_SENT;
} else {
return s;
}
} catch (Native.NotLinked notLinked) {
notLinked.printStackTrace();
}
}
return s;
});
}).start();
};
emailEditText.setOnEditorActionListener((v, i, ev) -> {
requestEmailChallenge.run();
return false;
});
emailEditText.setOnFocusChangeListener((view, b) -> {
if (view.isEnabled() && !b) {
requestEmailChallenge.run();
}
});
resendButton.setOnClickListener(v -> {
requestEmailChallenge.run();
});
changeButton.setOnClickListener(v -> {
focusEmail.run();
});
Button submitButton = rootView.findViewById(R.id.submitButton);
submitButton.setEnabled(false);
submitButton.setAlpha(0);
submitButton.setOnClickListener(v -> {
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
fragmentManager.beginTransaction().setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_right, R.anim.exit_to_left).replace(R.id.fragment_teams, new OnboardingLoadTeamFragment()).commitNowAllowingStateLoss();
}
});
EventBus.getDefault().register(this);
EventBus.getDefault().post(new IdentityService.GetProfile(getContext()));
return rootView;
}
use of co.krypt.krypton.protocol.Profile in project krypton-android by kryptco.
the class VerifyEmailFragment method onCreateView.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_teams_onboarding_verify_email, container, false);
Button cancelButton = rootView.findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(v -> {
progress.resetAndDeleteTeam(v.getContext());
getActivity().finish();
});
ProgressBar progressBar = rootView.findViewById(R.id.progressBar);
progressBar.setAlpha(0);
Button submitButton = rootView.findViewById(R.id.submitButton);
Button changeButton = rootView.findViewById(R.id.changeButton);
Button resendButton = rootView.findViewById(R.id.resendButton);
AppCompatTextView checkYourEmailText = rootView.findViewById(R.id.checkYourEmailText);
AppCompatTextView checkYourEmailSubtext = rootView.findViewById(R.id.checkYourEmailSubtext);
AppCompatEditText emailEditText = rootView.findViewById(R.id.profileEmail);
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
Runnable onSubmitUI = () -> {
emailEditText.setEnabled(false);
emailEditText.clearFocus();
if (imm != null) {
imm.hideSoftInputFromWindow(emailEditText.getWindowToken(), 0);
}
progressBar.animate().alpha(1).setDuration(1000).start();
submitButton.setEnabled(false);
submitButton.animate().alpha(0).setDuration(500).start();
checkYourEmailSubtext.animate().alpha(0).setDuration(500).start();
checkYourEmailText.animate().alpha(0).setDuration(500).start();
};
Runnable onEditUI = () -> {
emailEditText.setEnabled(true);
submitButton.animate().alpha(1).setDuration(500).start();
changeButton.animate().alpha(0).setDuration(500).start();
resendButton.animate().alpha(0).setDuration(500).start();
submitButton.setEnabled(true);
changeButton.setEnabled(false);
resendButton.setEnabled(false);
checkYourEmailSubtext.animate().alpha(0).setDuration(500).start();
checkYourEmailText.animate().alpha(0).setDuration(500).start();
progressBar.animate().alpha(0).setDuration(500).start();
};
Runnable onSuccessUI = () -> {
progressBar.animate().alpha(0).setDuration(500).start();
changeButton.animate().alpha(1).setDuration(1000).start();
resendButton.animate().alpha(1).setDuration(1000).start();
submitButton.animate().alpha(0).setDuration(500).start();
changeButton.setEnabled(true);
resendButton.setEnabled(true);
checkYourEmailSubtext.animate().alpha(1).setDuration(500).start();
checkYourEmailText.animate().alpha(1).setDuration(500).start();
};
Runnable focusEmail = () -> {
onEditUI.run();
emailEditText.requestFocus();
if (imm != null) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
};
Runnable onErrorUI = () -> {
focusEmail.run();
Toast.makeText(getContext(), "Error sending email verification.", Toast.LENGTH_SHORT).show();
};
submitButton.setAlpha(1);
changeButton.setAlpha(0);
resendButton.setAlpha(0);
checkYourEmailSubtext.setAlpha(0);
checkYourEmailText.setAlpha(0);
changeButton.setEnabled(false);
resendButton.setEnabled(false);
AppCompatTextView teamName = rootView.findViewById(R.id.teamName);
teamName.setText(progress.getTeamOnboardingData().decryptInviteOutput.teamName);
String initialEmail = Silo.shared(getContext().getApplicationContext()).meStorage().load().email;
emailEditText.setText(initialEmail);
final Sigchain.IndirectInvitationRestriction restriction = progress.getTeamOnboardingData().decryptInviteOutput.indirectInvitationSecret.restriction;
Runnable requestEmailChallenge = () -> {
final String email = emailEditText.getEditableText().toString();
if (!Email.verifyEmailPattern.matcher(email).matches()) {
Toast.makeText(getContext(), "Please enter a valid email.", Toast.LENGTH_SHORT).show();
return;
}
if (!restriction.isSatisfiedByEmail(email)) {
if (restriction.domain != null) {
Toast.makeText(getContext(), "Email must end with @" + restriction.domain, Toast.LENGTH_SHORT).show();
} else if (restriction.emails != null) {
Toast.makeText(getContext(), "Invite link not valid for this email address.", Toast.LENGTH_SHORT).show();
}
return;
}
onSubmitUI.run();
new Thread(() -> {
MeStorage meStorage = Silo.shared(getContext()).meStorage();
try {
meStorage.setEmail(email);
} catch (CryptoException e) {
co.krypt.krypton.uiutils.Error.shortToast(getContext(), "Failed to set email: " + e.getMessage());
e.printStackTrace();
return;
}
Profile me = meStorage.load();
progress.updateTeamData((s, d) -> {
if (s.equals(JoinStage.VERIFY_EMAIL)) {
d.profile = me;
Log.i(TAG, "requesting email challenge...");
try {
final Sigchain.NativeResult<JsonObject> result = TeamDataProvider.requestEmailChallenge(getContext(), email);
emailEditText.post(() -> {
if (result.success != null) {
Log.i(TAG, "request email challenge success");
onSuccessUI.run();
} else {
Log.i(TAG, "request email challenge failure");
onErrorUI.run();
}
});
if (result.success != null) {
return JoinStage.CHALLENGE_EMAIL_SENT;
} else {
return s;
}
} catch (Native.NotLinked notLinked) {
notLinked.printStackTrace();
}
}
return s;
});
}).start();
};
final Runnable setSelectionBeforeDomain = () -> {
String currentEmail = emailEditText.getText().toString();
if (restriction.domain != null) {
String domainSuffix = "@" + restriction.domain;
if (currentEmail.length() >= domainSuffix.length()) {
if (emailEditText.getSelectionStart() == emailEditText.getSelectionEnd()) {
if (emailEditText.getSelectionStart() > currentEmail.length() - domainSuffix.length()) {
emailEditText.setSelection(currentEmail.length() - domainSuffix.length());
}
}
}
}
};
emailEditText.setOnEditorActionListener((v, i, ev) -> {
requestEmailChallenge.run();
return false;
});
// focus before adding listener
focusEmail.run();
setSelectionBeforeDomain.run();
emailEditText.setOnFocusChangeListener((view, b) -> {
if (view.isEnabled()) {
if (b) {
setSelectionBeforeDomain.run();
}
}
});
emailEditText.setOnClickListener(v -> setSelectionBeforeDomain.run());
final AtomicReference<String> lastEmail = new AtomicReference<>(new String(emailEditText.getText().toString()));
if (!restriction.isSatisfiedByEmail(lastEmail.get())) {
if (restriction.domain != null) {
lastEmail.set("@" + restriction.domain);
} else if (restriction.emails != null && restriction.emails.length == 1) {
lastEmail.set(restriction.emails[0]);
} else {
lastEmail.set("");
}
emailEditText.setText(lastEmail.get());
}
final Runnable updateTextColor = () -> {
if (Email.verifyEmailPattern.matcher(emailEditText.getText()).matches()) {
emailEditText.setTextColor(getContext().getColor(R.color.appGreen));
} else {
emailEditText.setTextColor(getContext().getColor(R.color.appGray));
}
};
updateTextColor.run();
final TextWatcher domainCheck = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
lastEmail.set(s.toString());
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
updateTextColor.run();
}
@Override
public void afterTextChanged(Editable s) {
if (restriction.domain != null) {
if (!s.toString().endsWith("@" + restriction.domain)) {
emailEditText.removeTextChangedListener(this);
s.clear();
s.append(lastEmail.get());
setSelectionBeforeDomain.run();
emailEditText.addTextChangedListener(this);
Toast.makeText(getContext(), "Email must end with @" + restriction.domain, Toast.LENGTH_SHORT).show();
}
}
}
};
emailEditText.addTextChangedListener(domainCheck);
resendButton.setOnClickListener(v -> {
requestEmailChallenge.run();
});
changeButton.setOnClickListener(v -> {
focusEmail.run();
});
submitButton.setOnClickListener(v -> requestEmailChallenge.run());
return rootView;
}
Aggregations