Skip to content

Commit

Permalink
optional LockRequest on DELETE lock
Browse files Browse the repository at this point in the history
  • Loading branch information
cnuss committed May 11, 2022
1 parent a986660 commit 4499ad0
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 38 deletions.
14 changes: 9 additions & 5 deletions src/controllers/ControllerV1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,18 @@ export class ControllerV1 extends Controller {
@Delete('lock')
public async unlockState(
@Request() request: HttpRequest,
@Body() lockRequest: StateLockRequest,
@Res() res: TsoaResponse<200 | 401 | 403 | 404 | 409, boolean>,
@Query('force') force = false,
@Body() lockRequest?: StateLockRequest,
): Promise<boolean> {
try {
const stateLockRequest = await this.stateService.getRequest(lockRequest.ID);
const identity = await this.githubService.getIdentity(request, stateLockRequest);
await this.stateService.unlockState(identity, stateLockRequest, force);
if (lockRequest && lockRequest.ID) {
const stateLockRequest = await this.stateService.getRequest(lockRequest.ID);
const identity = await this.githubService.getIdentity(request, stateLockRequest);
await this.stateService.unlockState(identity, stateLockRequest);
} else {
const identity = await this.githubService.getIdentity(request);
await this.stateService.unlockState(identity);
}
const response = res(200, true);
return response;
} catch (e) {
Expand Down
12 changes: 6 additions & 6 deletions src/models/schemas/StateLockRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export const stateLockRequest = {
sk: Joi.string()
.regex(/statelock/) // statelock
.optional(),
ID: Joi.string().required(),
Operation: Joi.string().required(),
ID: Joi.string().optional(),
Operation: Joi.string().optional(),
Info: Joi.string().allow('').optional(),
Who: Joi.string().required(),
Version: Joi.string().required(),
Created: Joi.string().required(),
Path: Joi.string().allow('').required(),
Who: Joi.string().optional(),
Version: Joi.string().optional(),
Created: Joi.string().optional(),
Path: Joi.string().allow('').optional(),
stateLock: Joi.object({
pk: Joi.string().required(),
sk: Joi.string().required(),
Expand Down
40 changes: 13 additions & 27 deletions src/services/StateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ export class StateService {
throw new TerraformError(409, stateLockRequest);
}

if (!stateLockRequest.ID) {
console.warn(`Missing ID on stateLockRequest`);
throw new TerraformError(400);
}

try {
stateLock = await this.stateLockModel.model.create(
{
Expand Down Expand Up @@ -171,43 +176,24 @@ export class StateService {

public unlockState = async (
identity: IdentityWithToken,
stateLockRequest: StateLockRequest,
force: boolean,
stateLockRequest?: StateLockRequest,
): Promise<void> => {
const lockedBy = crypto.createHash('sha256').update(identity.token, 'utf8').digest('base64');

const path = stateLockRequest ? stateLockRequest.Path : '';
const pk = StateLockModel.prefix('pk', identity.ownerId);
const sk = StateLockModel.prefix('sk', `${identity.repoId}_${identity.workspace}`);
const id = stateLockRequest.ID;
const sk = StateLockModel.prefix('sk', `${identity.repoId}_${identity.workspace}_${path}`);

console.log('Releasing state lock');
console.log(`Releasing state lock (pk: ${pk} sk: ${sk})`);

const [stateLocks] = await this.stateLockModel.model
.query(pk)
.where('sk')
.beginsWith(sk)
.filter('id')
.eq(id)
.exec()
.promise();
const stateLock = await this.stateLockModel.model.get(pk, sk);

if (!stateLocks || !stateLocks.Count) {
if (!stateLock) {
console.log(
`No state locks for ${identity.ownerId}/${identity.repoId} on workspace ${identity.workspace} with id ${stateLockRequest.ID}`,
`No state locks for ${identity.ownerId}/${identity.repoId} on workspace ${identity.workspace} with path ${path}`,
);
return;
}

const [stateLock] = stateLocks.Items;

if (stateLock.attrs.lockedBy !== lockedBy && !force) {
console.warn(
`State is locked by ${identity.meta.name} for ${identity.owner}/${identity.repo} on workspace ${identity.workspace}.`,
);
throw new TerraformError(409, stateLockRequest);
}

await this.stateLockModel.model.destroy(stateLock.attrs.pk, stateLock.attrs.sk);
this.stateLockModel.model.destroy(stateLock.attrs.pk, stateLock.attrs.sk);
};

public saveRequest = async (stateLockRequest: StateLockRequest): Promise<StateLockRequest> => {
Expand Down

0 comments on commit 4499ad0

Please sign in to comment.