Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions api/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ To emulate Azure Blob Storage locally. Azurite needs to be installed and running

- `LOGIN_AUTHORIZED_DOMAINS`: Comma-separated list of additional email domains authorized to access the service via Google OAuth.

### Terms and Conditions

- `CURRENT_TERMS_VERSION`: Version string for the current terms and conditions that users must accept. Example: `v1.0`, `v2.1`. Defaults to `v1.0` if not set.

### HTTPS
- `HTTPS`: Set to 'true' to enable HTTPS for local deployment
Expand Down
4 changes: 2 additions & 2 deletions api/script/routes/authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export class Authentication {
private isEmailDomainAuthorized(email: string): boolean {
const authorizedDomains = process.env.LOGIN_AUTHORIZED_DOMAINS;

// Always include dream11.com as an allowed domain
let allowedDomains: string[] = ['dream11.com'];
// Initialize empty allowed domains array
let allowedDomains: string[] = [];

if (authorizedDomains && authorizedDomains.trim() !== '') {
// Parse comma-separated domains and normalize
Expand Down
99 changes: 0 additions & 99 deletions api/script/routes/management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,106 +176,7 @@ export function getManagementRouter(config: ManagementConfig): Router {
.catch((error: error.CodePushError) => errorUtils.restErrorHandler(res, error, next))
});

router.get("/account/ownerTermsStatus", (req: Request, res: Response, next: (err?: any) => void): any => {
const accountId: string = req.user.id;
const termsVersion = process.env.CURRENT_TERMS_VERSION || "v1.0";

// First check if user is an owner of at least one app
storage
.getAppOwnershipCount(accountId)
.then((ownershipCount: number) => {
if (ownershipCount === 0) {
// User is not an owner of any app
res.send({
accountId: accountId,
isOwner: false,
ownerAppCount: 0,
termsAccepted: false,
termsVersion: null,
message: "Logged in account is not an owner of any app"
});
return;
}

// User is an owner, now check terms acceptance
return storage.getTermsAcceptance(accountId)
.then((termsRecord: storageTypes.TermsAcceptance) => {
const isCurrentVersion = termsRecord.termsVersion === termsVersion;
res.send({
accountId: accountId,
isOwner: true,
ownerAppCount: ownershipCount,
termsAccepted: true,
termsVersion: termsRecord.termsVersion,
acceptedTime: termsRecord.acceptedTime,
isCurrentVersion: isCurrentVersion,
currentRequiredVersion: termsVersion
});
})
.catch((termsError: storageTypes.StorageError) => {
if (termsError.code === storageTypes.ErrorCode.NotFound) {
// User is owner but hasn't accepted terms yet
res.send({
accountId: accountId,
isOwner: true,
ownerAppCount: ownershipCount,
termsAccepted: false,
termsVersion: null,
acceptedTime: null,
isCurrentVersion: false,
currentRequiredVersion: termsVersion
});
} else {
// Other error occurred
errorUtils.restErrorHandler(res, termsError, next);
}
});
})
.catch((error: storageTypes.StorageError) => {
errorUtils.restErrorHandler(res, error, next);
});
});

router.post("/account/acceptTerms", (req: Request, res: Response, next: (err?: any) => void): any => {
const accountId: string = req.user.id;
const termsVersion = req.body.termsVersion;
console.log("termsVersion", termsVersion);

// Validate required fields
if (!termsVersion || typeof termsVersion !== 'string') {
res.status(400).send({ error: "termsVersion is required and must be a string" });
return;
}

// Get user account to retrieve email
storage
.getAccount(accountId)
.then((account: storageTypes.Account) => {
const termsData: storageTypes.TermsAcceptance = {
accountId: accountId,
email: account.email,
termsVersion: termsVersion,
acceptedTime: new Date().getTime()
};

return storage.addOrUpdateTermsAcceptance(termsData);
})
.then((savedTerms: storageTypes.TermsAcceptance) => {
res.status(201).send({
message: "Terms acceptance recorded successfully",
termsAcceptance: {
id: savedTerms.id,
accountId: savedTerms.accountId,
email: savedTerms.email,
termsVersion: savedTerms.termsVersion,
acceptedTime: savedTerms.acceptedTime
}
});
})
.catch((error: storageTypes.StorageError) => {
errorUtils.restErrorHandler(res, error, next);
});
});

router.patch("/accessKeys/:accessKeyName", (req: Request, res: Response, next: (err?: any) => void): any => {
const accountId: string = req.user.id;
Expand Down
81 changes: 0 additions & 81 deletions api/script/storage/aws-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,6 @@ export function createCollaborators(sequelize: Sequelize) {
})
}

//Create TermsAcceptance
export function createTermsAcceptance(sequelize: Sequelize) {
return sequelize.define("termsAcceptance", {
id: { type: DataTypes.STRING, allowNull: false, primaryKey: true },
accountId: {
type: DataTypes.STRING,
allowNull: false,
unique: true, // Prevents duplicate entries per account
references: {
model: 'accounts',
key: 'id',
}
},
email: { type: DataTypes.STRING, allowNull: false },
termsVersion: { type: DataTypes.STRING, allowNull: false },
acceptedTime: { type: DataTypes.BIGINT, allowNull: false }, // Epoch timestamp
})
}

//Create Deployment

Expand Down Expand Up @@ -246,7 +228,6 @@ export function createModelss(sequelize: Sequelize) {
const AppPointer = createAppPointer(sequelize);
const Collaborator = createCollaborators(sequelize);
const App = createApp(sequelize);
const TermsAcceptance = createTermsAcceptance(sequelize);

// Define associations

Expand Down Expand Up @@ -287,7 +268,6 @@ export function createModelss(sequelize: Sequelize) {
AppPointer,
Collaborator,
App,
TermsAcceptance,
};
}

Expand All @@ -312,7 +292,6 @@ export const MODELS = {
ACCOUNT : "account",
APPPOINTER: "AppPointer",
TENANT : "tenant",
TERMS_ACCEPTANCE : "termsAcceptance"
}

const DB_NAME = "codepushdb"
Expand Down Expand Up @@ -523,66 +502,6 @@ export class S3Storage implements storage.Storage {
.catch(S3Storage.storageErrorHandler);
}

// Terms acceptance methods
public getTermsAcceptance(accountId: string): Promise<storage.TermsAcceptance> {
return this.setupPromise
.then(() => {
return this.sequelize.models[MODELS.TERMS_ACCEPTANCE].findOne({
where: { accountId: accountId }
});
})
.then((result: any) => {
if (!result) {
throw storage.storageError(
storage.ErrorCode.NotFound,
`Terms acceptance record not found for account ${accountId}`
);
}
return {
id: result.id,
accountId: result.accountId,
email: result.email,
termsVersion: result.termsVersion,
acceptedTime: result.acceptedTime
};
})
.catch(S3Storage.storageErrorHandler);
}

public addOrUpdateTermsAcceptance(termsAcceptance: storage.TermsAcceptance): Promise<storage.TermsAcceptance> {
return this.setupPromise
.then(() => {
const termsData = {
id: termsAcceptance.id || security.generateSecureKey(termsAcceptance.accountId),
accountId: termsAcceptance.accountId,
email: termsAcceptance.email,
termsVersion: termsAcceptance.termsVersion,
acceptedTime: termsAcceptance.acceptedTime
// createdAt and updatedAt handled by Sequelize defaults
};

// Use upsert (INSERT ... ON DUPLICATE KEY UPDATE)
return this.sequelize.models[MODELS.TERMS_ACCEPTANCE].upsert(termsData, {
returning: true
});
})
.then(() => {
// After upsert, fetch the record to return it
return this.sequelize.models[MODELS.TERMS_ACCEPTANCE].findOne({
where: { accountId: termsAcceptance.accountId }
});
})
.then((result: any) => {
return {
id: result.id,
accountId: result.accountId,
email: result.email,
termsVersion: result.termsVersion,
acceptedTime: result.acceptedTime
};
})
.catch(S3Storage.storageErrorHandler);
}

public getAccountIdFromAccessKey(accessKey: string): Promise<string> {

Expand Down
20 changes: 1 addition & 19 deletions api/script/storage/azure-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ export class AzureStorage implements storage.Storage {
})
.catch(AzureStorage.azureErrorHandler);
}

// NOTE: This method is not implemented for azure storage
public getAppOwnershipCount(accountId: string): Promise<number> {
return Promise.reject(
Expand All @@ -325,25 +326,6 @@ export class AzureStorage implements storage.Storage {
);
}

// NOTE: Terms acceptance methods - stubs for Azure (not implemented)
public getTermsAcceptance(accountId: string): Promise<storage.TermsAcceptance> {
return Promise.reject(
storage.storageError(
storage.ErrorCode.Other,
"AzureStorage is not configured. Please use S3Storage or JsonStorage."
)
);
}

public addOrUpdateTermsAcceptance(termsAcceptance: storage.TermsAcceptance): Promise<storage.TermsAcceptance> {
return Promise.reject(
storage.storageError(
storage.ErrorCode.Other,
"AzureStorage is not configured. Please use S3Storage or JsonStorage."
)
);
}

public getAccountIdFromAccessKey(accessKey: string): Promise<string> {
const partitionKey: string = Keys.getShortcutAccessKeyPartitionKey(accessKey);
const rowKey: string = "";
Expand Down
34 changes: 0 additions & 34 deletions api/script/storage/json-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export class JsonStorage implements storage.Storage {
public packages: { [id: string]: storage.Package } = {};
public blobs: { [id: string]: string } = {};
public accessKeys: { [id: string]: storage.AccessKey } = {};
public termsAcceptance: { [accountId: string]: storage.TermsAcceptance } = {};

public accountToAppsMap: { [id: string]: string[] } = {};
public appToAccountMap: { [id: string]: string } = {};
Expand Down Expand Up @@ -242,39 +241,6 @@ export class JsonStorage implements storage.Storage {
});
}

// Terms acceptance methods
public getTermsAcceptance(accountId: string): Promise<storage.TermsAcceptance> {
const termsRecord = this.termsAcceptance[accountId];
if (!termsRecord) {
return JsonStorage.getRejectedPromise(storage.ErrorCode.NotFound);
}
return Promise.resolve(clone(termsRecord));
}

public addOrUpdateTermsAcceptance(termsAcceptance: storage.TermsAcceptance): Promise<storage.TermsAcceptance> {
const existingRecord = this.termsAcceptance[termsAcceptance.accountId];

if (existingRecord) {
// Update existing record
existingRecord.termsVersion = termsAcceptance.termsVersion;
existingRecord.acceptedTime = termsAcceptance.acceptedTime;
this.saveStateAsync();
return Promise.resolve(clone(existingRecord));
} else {
// Create new record
const newRecord: storage.TermsAcceptance = {
id: termsAcceptance.id || this.newId(),
accountId: termsAcceptance.accountId,
email: termsAcceptance.email,
termsVersion: termsAcceptance.termsVersion,
acceptedTime: termsAcceptance.acceptedTime
};

this.termsAcceptance[termsAcceptance.accountId] = newRecord;
this.saveStateAsync();
return Promise.resolve(clone(newRecord));
}
}

public getAccountIdFromAccessKey(accessKey: string): Promise<string> {
if (!this.accessKeyNameToAccountIdMap[accessKey]) {
Expand Down
10 changes: 0 additions & 10 deletions api/script/storage/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,6 @@ export interface Organization {
role: string;
}

export interface TermsAcceptance {
/*generated*/ id?: string;
accountId: string;
email: string;
termsVersion: string;
acceptedTime: number; // Epoch timestamp
}

export interface Deployment {
/*generated*/ createdTime?: number;
Expand Down Expand Up @@ -161,9 +154,6 @@ export interface Storage {
updateAccount(email: string, updates: Account): Promise<void>;
getAppOwnershipCount(accountId: string): Promise<number>;

// Terms acceptance methods
getTermsAcceptance(accountId: string): Promise<TermsAcceptance>;
addOrUpdateTermsAcceptance(termsAcceptance: TermsAcceptance): Promise<TermsAcceptance>;

getTenants(accountId: string): Promise<Organization[]>;
removeTenant(accountId: string, tenantId: string): Promise<void>;
Expand Down