This commit is contained in:
max-mironov 2018-03-29 14:39:53 +03:00
Родитель aadb748301
Коммит 9115e1bc7f
12 изменённых файлов: 63 добавлений и 65 удалений

Просмотреть файл

@ -10,8 +10,6 @@ _NOTE: Currently it supports only React-Native based apps._
* react-native-cli
* git
Please notice that the extension uses `.vscode` directory at the project root to store appcenter related information.
It uses `appcenter.json` file for it, no security-sensetive information here, please feel free to inspect/edit it if needed.
## How does it work
There are several possible scenarios how this extension could be used:

Просмотреть файл

@ -65,7 +65,7 @@ export default class AppCenterConfig {
this.logger.error(`Unable to save ${this.pathToAndroidStringResources}`);
return false;
}
this.logger.info(`Saved new data to${this.pathToAndroidStringResources}`);
this.logger.info(`Saved CodePush deployemnt key to ${this.pathToAndroidStringResources}`);
return true;
}
@ -95,7 +95,7 @@ export default class AppCenterConfig {
public saveMainPlist(): boolean {
const plistContents = plist.build(this.parsedInfoMainPlist);
fs.writeFileSync(this.mainPlistPath, plistContents);
this.logger.info(`Saved deployemnt key in ${this.mainPlistPath}`);
this.logger.info(`Saved CodePush deployemnt key in ${this.mainPlistPath}`);
return true;
}

Просмотреть файл

@ -3,11 +3,8 @@ import { createAppCenterClient, models } from "../api";
import { deleteUser, getUser, Profile, saveUser } from "./profile/profile";
export default class Auth {
public static getProfile(projectRootPath: string): Promise<Profile | null> {
if (!projectRootPath) {
return Promise.resolve(null);
}
const profile: Profile | null = getUser(projectRootPath);
public static getProfile(): Promise<Profile | null> {
const profile: Profile | null = getUser();
if (profile) {
return Promise.resolve(profile);
} else {
@ -15,13 +12,13 @@ export default class Auth {
}
}
public static doTokenLogin(token: string, projectRootPath: string): Promise<Profile | null> {
public static doTokenLogin(token: string): Promise<Profile | null> {
if (!token) {
return Promise.resolve(null);
}
return this.removeLoggedInUser(projectRootPath).then(() => {
return Auth.fetchUserInfoByTokenAndSave(token, projectRootPath).then((profile: Profile) => {
return this.removeLoggedInUser().then(() => {
return Auth.fetchUserInfoByTokenAndSave(token).then((profile: Profile) => {
return Promise.resolve(profile);
}).catch(() => {
return Promise.resolve(null);
@ -29,14 +26,14 @@ export default class Auth {
});
}
public static doLogout(projectRootPath: string): Promise<void> {
public static doLogout(): Promise<void> {
// TODO: Probably we need to delete token from server also?
return this.removeLoggedInUser(projectRootPath);
return this.removeLoggedInUser();
}
private static fetchUserInfoByTokenAndSave(token: string, projectRootPath: string): Promise<Profile> {
private static fetchUserInfoByTokenAndSave(token: string): Promise<Profile> {
return Auth.getUserInfo(token).then(userResponse => {
return saveUser(userResponse, { token: token }, projectRootPath).then((profile: Profile) => {
return saveUser(userResponse, { token: token }).then((profile: Profile) => {
return Promise.resolve(profile);
});
// tslint:disable-next-line:no-any
@ -50,8 +47,8 @@ export default class Auth {
return client.account.users.get();
}
private static removeLoggedInUser(projectRootPath: string): Promise<void> {
return deleteUser(projectRootPath).then(() => {
private static removeLoggedInUser(): Promise<void> {
return deleteUser().then(() => {
return Promise.resolve(void 0);
}).catch(() => { }); // Noop, it's ok if deletion fails
}

Просмотреть файл

@ -1,8 +1,17 @@
import * as os from "os";
import * as path from "path";
export const profileDirName = ".vscode";
export const profileFile = "appcenter.json";
export const profileDirName: string = ".vscode-appcenter";
export const profileFile = "VSCodeAppCenterProfile.json";
export function getProfileDir(projectRootPath: string): string {
return path.join(projectRootPath, profileDirName);
function getProfileDirParent(): string {
if (os.platform() === "win32") {
return process.env.AppData;
} else {
return os.homedir();
}
}
export function getProfileDir(): string {
return path.join(getProfileDirParent(), profileDirName);
}

Просмотреть файл

@ -40,7 +40,7 @@ class ProfileImpl implements Profile {
});
}
public save(projectRootPath: string): Profile {
public save(): Profile {
// tslint:disable-next-line:no-any
const profile: any = {
userId: this.userId,
@ -50,15 +50,15 @@ class ProfileImpl implements Profile {
defaultApp: this.currentApp
};
mkdirp.sync(getProfileDir(projectRootPath));
fs.writeFileSync(getProfileFilename(projectRootPath), JSON.stringify(profile, null, "\t"), { encoding: "utf8" });
mkdirp.sync(getProfileDir());
fs.writeFileSync(getProfileFilename(), JSON.stringify(profile, null, "\t"), { encoding: "utf8" });
return this;
}
public logout(projectRootPath: string): Promise<void> {
public logout(): Promise<void> {
return tokenStore.remove(this.userName).then(() => {
try {
fs.unlinkSync(getProfileFilename(projectRootPath));
fs.unlinkSync(getProfileFilename());
} catch (err) {
// File not found is ok, probably doesn't exist
}
@ -68,13 +68,13 @@ class ProfileImpl implements Profile {
let currentProfile: Profile | null;
function getProfileFilename(projectRootPath: string): string {
const profileDir = getProfileDir(projectRootPath);
function getProfileFilename(): string {
const profileDir = getProfileDir();
return path.join(profileDir, profileFile);
}
function loadProfile(projectRootPath: string): Profile | null {
const profilePath = getProfileFilename(projectRootPath);
function loadProfile(): Profile | null {
const profilePath = getProfileFilename();
if (!fs.existsSync(profilePath)) {
return null;
}
@ -85,27 +85,27 @@ function loadProfile(projectRootPath: string): Profile | null {
return new ProfileImpl(profile);
}
export function getUser(projectRootPath: string): Profile | null {
export function getUser(): Profile | null {
if (!currentProfile) {
currentProfile = loadProfile(projectRootPath);
currentProfile = loadProfile();
}
return currentProfile;
}
// tslint:disable-next-line:no-any
export function saveUser(user: any, token: TokenValueType, projectRootPath: string): Promise<Profile> {
export function saveUser(user: any, token: TokenValueType): Promise<Profile> {
return tokenStore.set(user.name, token).then(() => {
const profile = new ProfileImpl(user);
profile.save(projectRootPath);
profile.save();
return profile;
});
}
export function deleteUser(projectRootPath: string): Promise<void> {
const profile = getUser(projectRootPath);
export function deleteUser(): Promise<void> {
const profile = getUser();
if (profile) {
currentProfile = null;
return profile.logout(projectRootPath);
return profile.logout();
}
return Promise.resolve(void 0);
}

Просмотреть файл

@ -3,7 +3,7 @@ import { Profile } from "../../helpers/interfaces";
import { SettingsHelper } from "../../helpers/settingsHelper";
import { Strings } from "../../helpers/strings";
import { VsCodeUtils } from "../../helpers/vsCodeUtils";
import { ILogger, LogLevel } from "../../log/logHelper";
import { ILogger } from "../../log/logHelper";
import { AppCenterClient, AppCenterClientFactory, createAppCenterClient } from "../api";
import Auth from "../auth/auth";
@ -17,9 +17,9 @@ export class Command {
}
public get Profile(): Promise<Profile | null> {
return Auth.getProfile(<string>this.manager.projectRootPath).then((profile: Profile) => {
return Auth.getProfile().then((profile: Profile) => {
if (!profile) {
this.logger.log(`No profile found within "${this.manager.projectRootPath}" path`, LogLevel.Info);
this.logger.info(`No profile file found`);
return null;
}
return profile;
@ -29,7 +29,7 @@ export class Command {
public runNoClient(): Promise<boolean | void> {
const rootPath: string | undefined = this.manager.projectRootPath;
if (!rootPath) {
this.logger.log('No project root folder found', LogLevel.Info);
this.logger.error('No project root folder found');
VsCodeUtils.ShowInfoMessage(Strings.NoProjectRootFolderFound);
return Promise.resolve(false);
}
@ -40,7 +40,7 @@ export class Command {
public async run(): Promise<boolean | void> {
const rootPath: string | undefined = this.manager.projectRootPath;
if (!rootPath) {
this.logger.log('No project root path found.', LogLevel.Info);
this.logger.error('No project root folder found');
VsCodeUtils.ShowInfoMessage(Strings.NoProjectRootFolderFound);
return Promise.resolve(false);
}
@ -54,7 +54,7 @@ export class Command {
if (clientOrNull) {
this.client = clientOrNull;
} else {
this.logger.log("Failed to get App Center client", LogLevel.Info);
this.logger.error("Failed to get App Center client");
return Promise.resolve(false);
}
return Promise.resolve(true);
@ -66,7 +66,7 @@ export class Command {
if (profile) {
return this.clientFactory.fromProfile(profile, SettingsHelper.getAppCenterAPIEndpoint());
} else {
this.logger.log('No App Center user specified!', LogLevel.Error);
this.logger.error('No App Center user specified!');
return null;
}
}

Просмотреть файл

@ -7,7 +7,7 @@ import { Profile } from "../../helpers/interfaces";
import { SettingsHelper } from "../../helpers/settingsHelper";
import { Strings } from "../../helpers/strings";
import { IButtonMessageItem, VsCodeUtils } from "../../helpers/vsCodeUtils";
import { ILogger, LogLevel } from "../../log/logHelper";
import { ILogger } from "../../log/logHelper";
import Auth from "../auth/auth";
import { Command } from "./command";
@ -47,7 +47,7 @@ export default class Login extends Command {
});
default:
// User canel login otherwise
this.logger.log("User cancel login", LogLevel.Info);
this.logger.info("User cancel login");
return Promise.resolve(void 0);
}
});
@ -55,13 +55,13 @@ export default class Login extends Command {
private loginWithToken(token: string | undefined) {
if (!token) {
this.logger.log("No token detected on login", LogLevel.Error);
this.logger.error("No token provided on login");
return;
}
return Auth.doTokenLogin(token, <string>this.manager.projectRootPath).then((profile: Profile) => {
return Auth.doTokenLogin(token).then((profile: Profile) => {
if (!profile) {
this.logger.log("Failed to fetch user info from server", LogLevel.Error);
this.logger.error("Failed to fetch user info from server");
VsCodeUtils.ShowWarningMessage(Strings.FailedToExecuteLoginMsg);
return;
}

Просмотреть файл

@ -1,7 +1,7 @@
import { ExtensionManager } from "../../extensionManager";
import { Strings } from "../../helpers/strings";
import { VsCodeUtils } from "../../helpers/vsCodeUtils";
import { ILogger, LogLevel } from "../../log/logHelper";
import { ILogger } from "../../log/logHelper";
import Auth from "../auth/auth";
import { Command } from "./command";
@ -14,11 +14,11 @@ export default class Logout extends Command {
public async runNoClient(): Promise<void> {
await super.runNoClient();
return Auth.doLogout(<string>this.manager.projectRootPath).then(() => {
return Auth.doLogout().then(() => {
VsCodeUtils.ShowInfoMessage(Strings.UserLoggedOutMsg);
return this.manager.setupAppCenterStatusBar(null);
}).catch(() => {
this.logger.log("An error occured on logout", LogLevel.Error);
this.logger.error("Sorry, An error occured on logout");
});
}
}

Просмотреть файл

@ -37,7 +37,6 @@ export class ReactNativeAppCommand extends Command {
}
protected saveCurrentApp(
projectRootPath: string,
currentAppName: string,
appOS: AppCenterOS,
currentAppDeployments: CurrentAppDeployments | null,
@ -52,7 +51,7 @@ export class ReactNativeAppCommand extends Command {
return this.Profile.then((profile: Profile | null) => {
if (profile) {
profile.currentApp = defaultApp;
profile.save(projectRootPath);
profile.save();
return Promise.resolve(defaultApp);
} else {
// No profile - not logged in?

Просмотреть файл

@ -79,7 +79,6 @@ export default class SetCurrentApp extends ReactNativeAppCommand {
};
}
return this.saveCurrentApp(
this.manager.projectRootPath as string,
selectedAppName,
OS,
currentDeployments,

Просмотреть файл

@ -75,13 +75,9 @@ export class ExtensionManager implements Disposable {
private async initializeExtension(): Promise<void> {
this._appCenterCommandHandler = new AppCenterCommandHandler(this, this._logger);
this._appCenterStatusBarItem = VsCodeUtils.getStatusBarItem();
if (this._projectRootPath) {
Auth.getProfile(this._projectRootPath).then((profile: Profile | null) => {
return this.setupAppCenterStatusBar(profile);
});
} else {
this._logger.error('Extension Manager: No project root path defined');
}
Auth.getProfile().then((profile: Profile | null) => {
return this.setupAppCenterStatusBar(profile);
});
}
private cleanup(): void {

Просмотреть файл

@ -41,8 +41,8 @@ export interface Profile {
email: string;
readonly accessToken: Promise<string>;
currentApp?: CurrentApp;
save(projectRootPath: string): Profile;
logout(projectRootPath: string): Promise<void>;
save(): Profile;
logout(): Promise<void>;
}
export interface IDefaultCommandParams {