Skip to content

Commit 1200e31

Browse files
committed
chore: login working initial
1 parent 0eaafcf commit 1200e31

File tree

6 files changed

+114
-10
lines changed

6 files changed

+114
-10
lines changed

src/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"how_to_use_url": "https://github.com/adobe/brackets/wiki/How-to-Use-Brackets",
88
"docs_url": "https://docs.phcode.dev/",
99
"support_url": "https://github.com/phcode-dev/phoenix/discussions",
10+
"support_url_account": "https://account.phcode.io/?returnUrl=https%3A%2F%2Faccount.phcode.io%2F%23support",
1011
"suggest_feature_url": "https://github.com/phcode-dev/phoenix/discussions/categories/ideas",
1112
"report_issue_url": "https://github.com/phcode-dev/phoenix/issues/new/choose",
1213
"get_involved_url": "https://github.com/phcode-dev/phoenix/discussions/77",

src/nls/root/strings.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,5 +1572,10 @@ define({
15721572
"SIGNED_IN_OFFLINE_TITLE": "Offline - Cannot Sign In",
15731573
"SIGNED_IN_OFFLINE_MESSAGE": "Please connect to the internet to sign in to {APP_NAME}.",
15741574
"SIGNED_IN_FAILED_TITLE": "Cannot Sign In",
1575-
"SIGNED_IN_FAILED_MESSAGE": "Something went wrong while trying to sign in. Please try again."
1575+
"SIGNED_IN_FAILED_MESSAGE": "Something went wrong while trying to sign in. Please try again.",
1576+
"VALIDATION_CODE_TITLE": "Sign In Verification Code",
1577+
"VALIDATION_CODE_MESSAGE": "Please use this Verification code to sign in to your {APP_NAME} account:",
1578+
"COPY_VALIDATION_CODE": "Copy Code",
1579+
"VALIDATION_CODE_COPIED": "Copied",
1580+
"OPEN_SIGN_IN_URL": "Open Sign In Page"
15761581
});

src/phoenix/trust_ring.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ async function removeCredential(credKey) {
235235

236236
let _dismatled = false;
237237
async function dismantleKeyring() {
238-
if(!_dismatled){
238+
if(_dismatled){
239239
throw new Error("Keyring can only be dismantled once!");
240240
// and once dismantled, the next line should be reload page. this is a strict security posture requirement to
241241
// prevent extensions from stealing sensitive info from system key ring as once the trust in invalidated,

src/services/html/otp-dialog.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<div class="otp-dialog modal">
2+
<div class="modal-header">
3+
<h1 class="dialog-title">{{Strings.VALIDATION_CODE_TITLE}}</h1>
4+
</div>
5+
<div class="modal-body">
6+
<div class="validation-code-container">
7+
<p>{{Strings.VALIDATION_CODE_MESSAGE}}</p>
8+
<div class="validation-code" style="font-size: 24px; font-weight: bold; text-align: center; margin: 20px 0; padding: 10px; border-radius: 4px; letter-spacing: 2px; display: flex; justify-content: center; align-items: center;">
9+
<span>{{validationCode}}</span>
10+
<i class="fas fa-copy" data-button-id="copy" style="margin-left: 10px; cursor: pointer;" title="{{Strings.COPY_VALIDATION_CODE}}"></i>
11+
</div>
12+
</div>
13+
</div>
14+
<div class="modal-footer">
15+
<button class="btn" data-button-id="cancel">{{Strings.CANCEL}}</button>
16+
<button class="btn primary" data-button-id="open">{{Strings.OPEN_SIGN_IN_URL}}</button>
17+
</div>
18+
</div>

src/services/login.js

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ define(function (require, exports, module) {
2424
DefaultDialogs = require("widgets/DefaultDialogs"),
2525
Strings = require("strings"),
2626
NativeApp = require("utils/NativeApp"),
27-
ProfileMenu = require("./profile-menu");
27+
ProfileMenu = require("./profile-menu"),
28+
Mustache = require("thirdparty/mustache/mustache"),
29+
otpDialogTemplate = require("text!./html/otp-dialog.html");
2830

2931
const KernalModeTrust = window.KernalModeTrust;
3032
if(!KernalModeTrust){
@@ -42,6 +44,14 @@ define(function (require, exports, module) {
4244
// just used as trigger to notify different windows about user profile changes
4345
const PREF_USER_PROFILE_VERSION = "userProfileVersion";
4446

47+
EventDispatcher.makeEventDispatcher(exports);
48+
EventDispatcher.makeEventDispatcher(secureExports);
49+
50+
const _EVT_PAGE_FOCUSED = "page_focused";
51+
$(window).focus(function () {
52+
exports.trigger(_EVT_PAGE_FOCUSED);
53+
});
54+
4555

4656
function isLoggedIn() {
4757
return isLoggedInUser;
@@ -112,6 +122,7 @@ define(function (require, exports, module) {
112122
}
113123
// some error happened.
114124
if(resolveResponse.err === ERR_INVALID) { // the api key is invalid, we need to logout and tell user
125+
isLoggedInUser = false;
115126
ProfileMenu.setNotLoggedIn();
116127
Dialogs.showModalDialog(
117128
DefaultDialogs.DIALOG_ID_ERROR,
@@ -166,8 +177,79 @@ define(function (require, exports, module) {
166177
}
167178
const {appSessionID, validationCode} = appAuthSession;
168179
const appSignInURL = `${Phoenix.config.account_url}authorizeApp?appSessionID=${appSessionID}`;
169-
// show a dialog here with the 6 letter validation code and a button to copy the validation code and another
170-
// button to open the sign in code
180+
181+
// Show dialog with validation code
182+
const dialogData = {
183+
validationCode: validationCode,
184+
Strings: Strings
185+
};
186+
187+
const $template = $(Mustache.render(otpDialogTemplate, dialogData));
188+
const dialog = Dialogs.showModalDialogUsingTemplate($template);
189+
190+
// Set timeout to close dialog after 5 minutes, as validity is only 5 mins
191+
const closeTimeout = setTimeout(() => {
192+
dialog.close();
193+
}, 5 * 60 * 1000);
194+
195+
// Handle button clicks
196+
$template.on('click', '[data-button-id="copy"]', function() {
197+
Phoenix.app.copyToClipboard(validationCode);
198+
199+
// Show "Copied" feedback
200+
const $validationCodeSpan = $template.find('.validation-code span');
201+
const originalText = $validationCodeSpan.text();
202+
203+
// Replace validation code with "Copied" text
204+
$validationCodeSpan.text(Strings.VALIDATION_CODE_COPIED);
205+
206+
// Restore original validation code after 1.5 seconds
207+
setTimeout(() => {
208+
$validationCodeSpan.text(originalText);
209+
}, 1500);
210+
});
211+
212+
$template.on('click', '[data-button-id="open"]', function() {
213+
NativeApp.openURLInDefaultBrowser(appSignInURL);
214+
});
215+
$template.on('click', '[data-button-id="cancel"]', function() {
216+
dialog.close();
217+
});
218+
219+
let checking = false, checkAgain = false;
220+
async function checkLoginStatus() {
221+
if(checking) {
222+
checkAgain = true;
223+
return;
224+
}
225+
checking = true;
226+
try {
227+
const resolveResponse = await _resolveAPIKey(appSessionID, validationCode);
228+
if(resolveResponse.userDetails) {
229+
// the user has validated the creds
230+
userProfile = resolveResponse.userDetails;
231+
ProfileMenu.setLoggedIn(userProfile.profileIcon.initials, userProfile.profileIcon.color);
232+
await KernalModeTrust.setCredential(KernalModeTrust.CRED_KEY_API, JSON.stringify(userProfile));
233+
checkAgain = false;
234+
isLoggedInUser = true;
235+
dialog.close();
236+
}
237+
} catch (e) {
238+
console.error("Failed to check login status.", e);
239+
}
240+
checking = false;
241+
if(checkAgain) {
242+
checkAgain = false;
243+
setTimeout(checkLoginStatus, 100);
244+
}
245+
}
246+
exports.on(_EVT_PAGE_FOCUSED, checkLoginStatus);
247+
248+
// Clean up when dialog is closed
249+
dialog.done(function() {
250+
exports.off(_EVT_PAGE_FOCUSED, checkLoginStatus);
251+
clearTimeout(closeTimeout);
252+
});
171253
NativeApp.openURLInDefaultBrowser(appSignInURL);
172254
}
173255

@@ -187,8 +269,6 @@ define(function (require, exports, module) {
187269

188270
// no sensitive apis or events should be triggered from the public exports of this module as extensions
189271
// can read them. Always use KernalModeTrust.loginService for sensitive apis.
190-
EventDispatcher.makeEventDispatcher(exports);
191-
EventDispatcher.makeEventDispatcher(secureExports);
192272

193273
// kernal exports
194274
secureExports.isLoggedIn = isLoggedIn;

src/services/profile-menu.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ define(function (require, exports, module) {
1313

1414
function _createSVGIcon(initials, bgColor) {
1515
return `<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
16-
<circle cx="12" cy="12" r="12" fill="${bgColor}"/>
16+
<circle cx="12" cy="12" r="10" fill="${bgColor}"/>
1717
<text x="50%" y="58%" text-anchor="middle" font-size="11" fill="#fff" font-family="Inter, sans-serif" dy=".1em">
1818
${initials}</text>
1919
</svg>`;
@@ -74,11 +74,11 @@ define(function (require, exports, module) {
7474
}
7575

7676
function _handleContactSupportBtnClick() {
77-
Phoenix.app.openURLInDefaultBrowser(brackets.config.support_url);
77+
Phoenix.app.openURLInDefaultBrowser(brackets.config.support_url_account);
7878
}
7979

8080
function _handleAccountDetailsBtnClick() {
81-
console.log("User clicked account details");
81+
Phoenix.app.openURLInDefaultBrowser(brackets.config.account_url);
8282
}
8383

8484
/**

0 commit comments

Comments
 (0)