Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat add api endoints for file storage 2082 #4715

Merged
merged 1 commit into from
Feb 13, 2025
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
27 changes: 27 additions & 0 deletions api/admin/controllers/file-storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const EventCreator = require('../../services/EventCreator');
const { canAdminCreateSiteFileStorage } = require('../../authorizers/file-storage');
const { serializeFileStorageService } = require('../../serializers/file-storage');
const { wrapHandlers } = require('../../utils');
const { Event } = require('../../models');
const { adminCreateSiteFileStorage } = require('../../services/file-storage');

module.exports = wrapHandlers({
async createSiteFileStorage(req, res) {
const { params, user } = req;

const siteId = parseInt(params.id, 10);
const { site } = await canAdminCreateSiteFileStorage(siteId);

const fss = await adminCreateSiteFileStorage(site);

EventCreator.audit(
Event.labels.ADMIN,
user,
'Site File Storage Service Created',
fss,
);

const data = serializeFileStorageService(fss);
return res.send(data);
},
});
2 changes: 2 additions & 0 deletions api/admin/controllers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Build = require('./build');
const Domain = require('./domain');
const Event = require('./event');
const FileStorage = require('./file-storage');
const Organization = require('./organization');
const OrganizationRole = require('./organization-role');
const Role = require('./role');
Expand All @@ -13,6 +14,7 @@ module.exports = {
Build,
Domain,
Event,
FileStorage,
Organization,
OrganizationRole,
Role,
Expand Down
4 changes: 4 additions & 0 deletions api/admin/routers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ apiRouter.get('/sites', AdminControllers.Site.list);
apiRouter.get('/sites/raw', AdminControllers.Site.listRaw);
apiRouter.get('/sites/:id', AdminControllers.Site.findById);
apiRouter.put('/sites/:id', AdminControllers.Site.update);
apiRouter.post(
'/sites/:id/file-storage',
AdminControllers.FileStorage.createSiteFileStorage,
);
apiRouter.get('/sites/:id/webhooks', AdminControllers.Site.listWebhooks);
apiRouter.post('/sites/:id/webhooks', AdminControllers.Site.createWebhook);
apiRouter.delete('/sites/:id', authorize(['pages.admin']), AdminControllers.Site.destroy);
Expand Down
76 changes: 76 additions & 0 deletions api/authorizers/file-storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const siteErrors = require('../responses/siteErrors');
const { FileStorageService, Site } = require('../models');
const { isSiteOrgManager, isOrgManager, isOrgUser } = require('./utils');

const canCreateSiteStorage = async (userId, siteId) => {
const { site, organization } = await isSiteOrgManager(userId, siteId);

const fss = await FileStorageService.findOne({ where: { siteId } });

if (fss) {
throw {
status: 403,
message: siteErrors.SITE_FILE_STORAGE_EXISTS,
};
}

return { site, organization };
};

const canAdminCreateSiteFileStorage = async (siteId) => {
const site = await Site.findByPk(siteId);

if (!site) {
throw {
status: 403,
message: siteErrors.SITE_DOES_NOT_EXIST,
};
}

const fss = await FileStorageService.findOne({ where: { siteId } });

if (fss) {
throw {
status: 403,
message: siteErrors.SITE_FILE_STORAGE_EXISTS,
};
}

return { site };
};

async function hasFileStorage(fssId) {
const fileStorageService = await FileStorageService.findByPk(fssId);

if (!fileStorageService) {
throw {
status: 404,
message: siteErrors.NOT_FOUND,
};
}

return { fileStorageService };
}

async function isFileStorageManager(userId, fssId) {
const { fileStorageService } = await hasFileStorage(fssId);

const { organization } = await isOrgManager(userId, fileStorageService.organizationId);

return { organization, fileStorageService };
}

async function isFileStorageUser(userId, fssId) {
const { fileStorageService } = await hasFileStorage(fssId);

const { organization } = await isOrgUser(userId, fileStorageService.organizationId);

return { fileStorageService, organization };
}

module.exports = {
canAdminCreateSiteFileStorage,
canCreateSiteStorage,
isFileStorageManager,
isFileStorageUser,
};
42 changes: 7 additions & 35 deletions api/authorizers/site.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
const GitHub = require('../services/GitHub');
const siteErrors = require('../responses/siteErrors');
const { Organization, Site } = require('../models');
const { fetchModelById } = require('../utils/queryDatabase');

const authorize = async ({ id: userId }, { id: siteId }) => {
const site = await fetchModelById(
siteId,
Site.forUser({
id: userId,
}),
);

if (!site) {
throw 403;
}

if (!site.isActive) {
// if site is not active
throw 403;
}

if (site.organizationId) {
// if site exists in an org
const org = await site.getOrganization();
if (!org.isActive) {
throw 403;
}
}

return site;
};
const { Organization } = require('../models');
const { authorize } = require('./utils');

const authorizeRepositoryAdmin = (user, site) =>
GitHub.checkPermissions(user, site.owner, site.repository)
Expand Down Expand Up @@ -101,16 +73,16 @@ const create = async (user, siteParams) => {
}
};

const createBuild = (user, site) => authorize(user, site);
const createBuild = (user, site) => authorize(user.id, site.id);

const showActions = (user, site) => authorize(user, site);
const showActions = (user, site) => authorize(user.id, site.id);

const findOne = (user, site) => authorize(user, site);
const findOne = (user, site) => authorize(user.id, site.id);

const update = (user, site) => authorize(user, site);
const update = (user, site) => authorize(user.id, site.id);

const destroy = (user, site) =>
authorize(user, site).then(() => authorizeRepositoryAdmin(user, site));
authorize(user.id, site.id).then(() => authorizeRepositoryAdmin(user, site));

module.exports = {
create,
Expand Down
90 changes: 90 additions & 0 deletions api/authorizers/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const siteErrors = require('../responses/siteErrors');
const { Organization, Site } = require('../models');
const { fetchModelById } = require('../utils/queryDatabase');

const authorize = async (userId, siteId) => {
const site = await fetchModelById(
siteId,
Site.forUser({
id: userId,
}),
);

if (!site) {
throw {
status: 404,
message: siteErrors.NOT_FOUND,
};
}

if (!site.isActive) {
// if site is not active
throw {
status: 403,
message: siteErrors.ORGANIZATION_INACTIVE,
};
}

if (site.organizationId) {
// if site exists in an org
const org = await site.getOrganization();
if (!org.isActive) {
throw {
status: 403,
message: siteErrors.ORGANIZATION_INACTIVE,
};
}
}

return site;
};

const isSiteOrgManager = async (userId, siteId) => {
const site = await authorize(userId, siteId);
const organization = await fetchModelById(
site.organizationId,
Organization.forManagerRole({ id: userId }),
);

if (!organization) {
throw {
status: 403,
message: siteErrors.ORGANIZATION_MANAGER_ACCESS,
};
}

return { site, organization };
};

const isOrgManager = async (userId, orgId) => {
const organization = await fetchModelById(
orgId,
Organization.forManagerRole({ id: userId }),
);

if (!organization) {
throw {
status: 403,
message: siteErrors.ORGANIZATION_MANAGER_ACCESS,
};
}

return { organization };
};

const isOrgUser = async (userId, orgId) => {
const organization = await fetchModelById(orgId, Organization.forUser({ id: userId }));

if (!organization) {
throw {
status: 403,
message: siteErrors.ORGANIZATION_USER_ACCESS,
};
}

return { organization };
};

const isSiteUser = authorize;

module.exports = { authorize, isOrgManager, isOrgUser, isSiteOrgManager, isSiteUser };
Loading
Loading