api-viewer: show permissions

This commit is contained in:
Dietmar Maurer 2021-02-22 12:01:24 +01:00
parent 7f07991035
commit 2037d9af03
2 changed files with 111 additions and 22 deletions

View File

@ -110,6 +110,45 @@ Ext.onReady(function() {
return path.replace(/^.*\/_upgrade_(\/)?/, "/"); return path.replace(/^.*\/_upgrade_(\/)?/, "/");
}; };
var permission_text = function(permission) {
let permhtml = "";
if (permission.user) {
if (!permission.description) {
if (permission.user === 'world') {
permhtml += "Accessible without any authentication.";
} else if (permission.user === 'all') {
permhtml += "Accessible by all authenticated users.";
} else {
permhtml += 'Onyl accessible by user "' +
permission.user + '"';
}
}
} else if (permission.check) {
permhtml += "<pre>Check: " +
Ext.htmlEncode(Ext.JSON.encode(permission.check)) + "</pre>";
} else if (permission.userParam) {
permhtml += `<div>Check if user matches parameter '${permission.userParam}'`;
} else if (permission.or) {
permhtml += "<div>Or<div style='padding-left: 10px;'>";
Ext.Array.each(permission.or, function(sub_permission) {
permhtml += permission_text(sub_permission);
})
permhtml += "</div></div>";
} else if (permission.and) {
permhtml += "<div>And<div style='padding-left: 10px;'>";
Ext.Array.each(permission.and, function(sub_permission) {
permhtml += permission_text(sub_permission);
})
permhtml += "</div></div>";
} else {
//console.log(permission);
permhtml += "Unknown systax!";
}
return permhtml;
};
var render_docu = function(data) { var render_docu = function(data) {
var md = data.info; var md = data.info;
@ -339,28 +378,13 @@ Ext.onReady(function() {
permhtml += "<div style='white-space:pre-wrap;padding-bottom:10px;'>" + permhtml += "<div style='white-space:pre-wrap;padding-bottom:10px;'>" +
Ext.htmlEncode(info.permissions.description) + "</div>"; Ext.htmlEncode(info.permissions.description) + "</div>";
} }
permhtml += permission_text(info.permissions);
}
if (info.permissions.user) { // we do not have this information for PBS api
if (!info.permissions.description) { //if (!info.allowtoken) {
if (info.permissions.user === 'world') { // permhtml += "<br />This API endpoint is not available for API tokens."
permhtml += "Accessible without any authentication."; //}
} else if (info.permissions.user === 'all') {
permhtml += "Accessible by all authenticated users.";
} else {
permhtml += 'Onyl accessible by user "' +
info.permissions.user + '"';
}
}
} else if (info.permissions.check) {
permhtml += "<pre>Check: " +
Ext.htmlEncode(Ext.JSON.encode(info.permissions.check)) + "</pre>";
} else {
permhtml += "Unknown systax!";
}
}
if (!info.allowtoken) {
permhtml += "<br />This API endpoint is not available for API tokens."
}
sections.push({ sections.push({
title: 'Required permissions', title: 'Required permissions',

View File

@ -9,6 +9,9 @@ use proxmox::{
SchemaPropertyEntry, SchemaPropertyEntry,
ApiStringFormat, ApiStringFormat,
}, },
router::{
ApiAccess,
},
format::{ format::{
dump_enum_properties, dump_enum_properties,
dump_section_config, dump_section_config,
@ -18,12 +21,16 @@ use proxmox::{
ApiHandler, ApiHandler,
Router, Router,
SubRoute, SubRoute,
Permission,
}, },
}; };
use proxmox_backup::{ use proxmox_backup::{
api2, api2,
config, config::{
self,
acl::PRIVILEGES,
},
}; };
fn get_args() -> (String, Vec<String>) { fn get_args() -> (String, Vec<String>) {
@ -235,6 +242,51 @@ pub fn dump_property_schema<I>(
data data
} }
fn dump_api_permission(permission: &Permission) -> Value {
match permission {
Permission::Superuser => json!({ "user": "root@pam" }),
Permission::User(user) => json!({ "user": user }),
Permission::Anybody => json!({ "user": "all" }),
Permission::World => json!({ "user": "world" }),
Permission::UserParam(param) => json!({ "userParam": param }),
Permission::Group(group) => json!({ "group": group }),
Permission::WithParam(param, sub_permission) => {
json!({
"withParam": {
"name": param,
"permissions": dump_api_permission(sub_permission),
},
})
}
Permission::Privilege(name, value, partial) => {
let mut privs = Vec::new();
for (name, v) in PRIVILEGES {
if (value & v) != 0 {
privs.push(name.to_string());
}
}
json!({
"check": {
"path": name,
"privs": privs,
"partial": partial,
}
})
}
Permission::And(list) => {
let list: Vec<Value> = list.iter().map(|p| dump_api_permission(p)).collect();
json!({ "and": list })
}
Permission::Or(list) => {
let list: Vec<Value> = list.iter().map(|p| dump_api_permission(p)).collect();
json!({ "or": list })
}
}
}
fn dump_api_method_schema( fn dump_api_method_schema(
method: &str, method: &str,
api_method: &ApiMethod, api_method: &ApiMethod,
@ -251,6 +303,19 @@ fn dump_api_method_schema(
} }
data["returns"] = returns; data["returns"] = returns;
match api_method.access {
ApiAccess { description: None, permission: Permission::Superuser } => {
// no need to output default
}
ApiAccess { description, permission } => {
let mut permissions = dump_api_permission(permission);
if let Some(description) = description {
permissions["description"] = description.into();
}
data["permissions"] = permissions;
}
}
let mut method = method; let mut method = method;
if let ApiHandler::AsyncHttp(_) = api_method.handler { if let ApiHandler::AsyncHttp(_) = api_method.handler {