273 lines
12 KiB
JavaScript
273 lines
12 KiB
JavaScript
const { Controller } = require('libflitter')
|
|
|
|
class AppController extends Controller {
|
|
static get services() {
|
|
return [...super.services, 'models', 'utility']
|
|
}
|
|
|
|
async get_applications(req, res, next) {
|
|
const Application = this.models.get('Application')
|
|
const applications = await Application.find({ active: true })
|
|
const data = []
|
|
|
|
for ( const app of applications ) {
|
|
if ( req.user.can(`app:${app.id}:view`) ) {
|
|
data.push(await app.to_api())
|
|
}
|
|
}
|
|
|
|
return res.api(data)
|
|
}
|
|
|
|
async get_application(req, res, next) {
|
|
const Application = this.models.get('Application')
|
|
const application = await Application.findById(req.params.id)
|
|
|
|
if ( !application || !application.active )
|
|
return res.status(404)
|
|
.message('Application not found with that ID.')
|
|
.api()
|
|
|
|
if ( !req.user.can(`app:${application.id}:view`) )
|
|
return res.status(401)
|
|
.message('Insufficient permissions.')
|
|
.api()
|
|
|
|
return res.api(await application.to_api())
|
|
}
|
|
|
|
async create_application(req, res, next) {
|
|
const Application = this.models.get('Application')
|
|
|
|
if ( !req.user.can('app:create') )
|
|
return res.status(401)
|
|
.message('Insufficient permissions.')
|
|
.api()
|
|
|
|
const required_fields = ['name', 'identifier']
|
|
for ( const field of required_fields ) {
|
|
if ( !req.body[field] )
|
|
return res.status(400)
|
|
.message(`Missing required field: ${field}`)
|
|
.api()
|
|
}
|
|
|
|
// Make sure the identifier is properly formatted
|
|
if ( !(new RegExp('^[a-zA-Z0-9_]*$')).test(req.body.identifier) )
|
|
return res.status(400)
|
|
.message('Improperly formatted field: identifier (alphanumeric with underscores only)')
|
|
.api()
|
|
|
|
// Make sure the identifier is unique
|
|
const existing_app = await Application.findOne({ identifier: req.body.identifier })
|
|
if ( existing_app )
|
|
return res.status(400)
|
|
.message('An Application with that identifier already exists.')
|
|
.api()
|
|
|
|
const application = new Application({
|
|
name: req.body.name,
|
|
identifier: req.body.identifier,
|
|
description: req.body.description,
|
|
})
|
|
|
|
// Verify LDAP client IDs
|
|
const LDAPClient = this.models.get('ldap:Client')
|
|
if ( req.body.ldap_client_ids ) {
|
|
const parsed = typeof req.body.ldap_client_ids === 'string' ? this.utility.infer(req.body.ldap_client_ids) : req.body.ldap_client_ids
|
|
const ldap_client_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of ldap_client_ids ) {
|
|
const client = await LDAPClient.findById(id)
|
|
if ( !client || !client.active || !req.user.can(`ldap:client:${client.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid ldap_client_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ ldap_client_ids: client.id })
|
|
if ( other_assoc_app )
|
|
return res.status(400)
|
|
.message(`The LDAP client ${client.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.ldap_client_ids = ldap_client_ids
|
|
}
|
|
|
|
// Verify OAuth client IDs
|
|
const OAuthClient = this.models.get('oauth:Client')
|
|
if ( req.body.oauth_client_ids ) {
|
|
const parsed = typeof req.body.oauth_client_ids === 'string' ? this.utility.infer(req.body.oauth_client_ids) : req.body.oauth_client_ids
|
|
const oauth_client_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of oauth_client_ids ) {
|
|
const client = await OAuthClient.findById(id)
|
|
if ( !client || !client.active || !req.user.can(`oauth:client:${client.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid oauth_client_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ oauth_client_ids: client.id })
|
|
if ( other_assoc_app )
|
|
return res.status(400)
|
|
.message(`The OAuth2 client ${client.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.oauth_client_ids = oauth_client_ids
|
|
}
|
|
|
|
// Verify SAML service provider IDs
|
|
const ServiceProvider = this.models.get('saml:ServiceProvider')
|
|
if ( req.body.saml_service_provider_ids ) {
|
|
const parsed = typeof req.body.saml_service_provider_ids === 'string' ? this.utility.infer(req.body.saml_service_provider_ids) : req.body.saml_service_provider_ids
|
|
const saml_service_provider_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of saml_service_provider_ids ) {
|
|
const provider = await ServiceProvider.findById(id)
|
|
if ( !provider || !provider.active || !req.user.can(`saml:provider:${provider.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid saml_service_provider_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ saml_service_provider_ids: provider.id })
|
|
if ( other_assoc_app )
|
|
return res.status(400)
|
|
.message(`The SAML service provider ${provider.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.saml_service_provider_ids = saml_service_provider_ids
|
|
}
|
|
|
|
await application.save()
|
|
return res.api(await application.to_api())
|
|
}
|
|
|
|
async update_application(req, res, next) {
|
|
const Application = this.models.get('Application')
|
|
const application = await Application.findById(req.params.id)
|
|
|
|
if ( !application || !application.active )
|
|
return res.status(404)
|
|
.message('Application not found with that ID.')
|
|
.api()
|
|
|
|
if ( !req.user.can(`app:${application.id}:update`) )
|
|
return res.status(401)
|
|
.message('Insufficient permissions.')
|
|
.api()
|
|
|
|
const required_fields = ['name', 'identifier']
|
|
for ( const field of required_fields ) {
|
|
if ( !req.body[field] )
|
|
return res.status(400)
|
|
.message(`Missing required field: ${field}`)
|
|
.api()
|
|
}
|
|
|
|
// Make sure the identifier is properly formatted
|
|
if ( !(new RegExp('^[a-zA-Z0-9_]*$')).test(req.body.identifier) )
|
|
return res.status(400)
|
|
.message('Improperly formatted field: identifier (alphanumeric with underscores only)')
|
|
.api()
|
|
|
|
// Make sure the identifier is unique
|
|
const existing_app = await Application.findOne({ identifier: req.body.identifier })
|
|
if ( existing_app && existing_app.id !== application.id )
|
|
return res.status(400)
|
|
.message('An Application with that identifier already exists.')
|
|
.api()
|
|
|
|
// Verify LDAP client IDs
|
|
const LDAPClient = this.models.get('ldap:Client')
|
|
if ( req.body.ldap_client_ids ) {
|
|
const parsed = typeof req.body.ldap_client_ids === 'string' ? this.utility.infer(req.body.ldap_client_ids) : req.body.ldap_client_ids
|
|
const ldap_client_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of ldap_client_ids ) {
|
|
const client = await LDAPClient.findById(id)
|
|
if ( !client || !client.active || !req.user.can(`ldap:client:${client.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid ldap_client_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ ldap_client_ids: client.id })
|
|
if ( other_assoc_app && other_assoc_app.id !== application.id )
|
|
return res.status(400)
|
|
.message(`The LDAP client ${client.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.ldap_client_ids = ldap_client_ids
|
|
} else application.ldap_client_ids = []
|
|
|
|
// Verify OAuth client IDs
|
|
const OAuthClient = this.models.get('oauth:Client')
|
|
if ( req.body.oauth_client_ids ) {
|
|
const parsed = typeof req.body.oauth_client_ids === 'string' ? this.utility.infer(req.body.oauth_client_ids) : req.body.oauth_client_ids
|
|
const oauth_client_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of oauth_client_ids ) {
|
|
const client = await OAuthClient.findById(id)
|
|
if ( !client || !client.active || !req.user.can(`oauth:client:${client.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid oauth_client_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ oauth_client_ids: client.id })
|
|
if ( other_assoc_app && other_assoc_app.id !== application.id )
|
|
return res.status(400)
|
|
.message(`The OAuth2 client ${client.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.oauth_client_ids = oauth_client_ids
|
|
} else application.oauth_client_ids = []
|
|
|
|
// Verify SAML service provider IDs
|
|
const ServiceProvider = this.models.get('saml:ServiceProvider')
|
|
if ( req.body.saml_service_provider_ids ) {
|
|
const parsed = typeof req.body.saml_service_provider_ids === 'string' ? this.utility.infer(req.body.saml_service_provider_ids) : req.body.saml_service_provider_ids
|
|
const saml_service_provider_ids = Array.isArray(parsed) ? parsed : [parsed]
|
|
for ( const id of saml_service_provider_ids ) {
|
|
const provider = await ServiceProvider.findById(id)
|
|
if ( !provider || !provider.active || !req.user.can(`saml:provider:${provider.id}:view`) )
|
|
return res.status(400)
|
|
.message(`Invalid saml_service_provider_id: ${id}`)
|
|
.api()
|
|
|
|
const other_assoc_app = await Application.findOne({ saml_service_provider_ids: provider.id })
|
|
if ( other_assoc_app && other_assoc_app.id !== application.id )
|
|
return res.status(400)
|
|
.message(`The SAML service provider ${provider.name} is already associated with an existing application (${other_assoc_app.name}).`)
|
|
.api()
|
|
}
|
|
|
|
application.saml_service_provider_ids = saml_service_provider_ids
|
|
} else application.saml_service_provider_ids = []
|
|
|
|
application.name = req.body.name
|
|
application.identifier = req.body.identifier
|
|
application.description = req.body.description
|
|
await application.save()
|
|
return res.api(await application.to_api())
|
|
}
|
|
|
|
async delete_application(req, res, next) {
|
|
const Application = this.models.get('Application')
|
|
const application = await Application.findById(req.params.id)
|
|
|
|
if ( !application || !application.active )
|
|
return res.status(404)
|
|
.message('Application not found with that ID.')
|
|
.api()
|
|
|
|
if ( !req.user.can(`app:${application.id}:delete`) )
|
|
return res.status(401)
|
|
.message('Insufficient permissions.')
|
|
.api()
|
|
|
|
application.active = false
|
|
await application.save()
|
|
return res.api()
|
|
}
|
|
}
|
|
|
|
module.exports = exports = AppController
|