1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-26 19:47:20 +00:00

#8756 main page recipes (#8766)

This commit is contained in:
webplusai 2024-11-21 11:34:45 +01:00 committed by GitHub
parent 266b32bfee
commit 0cd2190ddf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 23 deletions

View File

@ -31,9 +31,14 @@ exports.useACL = true;
exports.entityName = "recipe"
exports.handler = function(request,response,state) {
var server = state.server,
sqlTiddlerDatabase = server.sqlTiddlerDatabase
if(state.data.recipe_name && state.data.bag_names) {
const result = $tw.mws.store.createRecipe(state.data.recipe_name,$tw.utils.parseStringArray(state.data.bag_names),state.data.description);
if(!result) {
if(state.authenticatedUser) {
sqlTiddlerDatabase.assignRecipeToUser(state.data.recipe_name,state.authenticatedUser.user_id);
}
state.sendResponse(302,{
"Content-Type": "text/plain",
"Location": "/"

View File

@ -48,33 +48,44 @@ exports.middleware = function (request, response, state, entityType, permissionN
var aclRecord = sqlTiddlerDatabase.getACLByName(entityType, decodedEntityName);
var isGetRequest = request.method === "GET";
var hasAnonymousAccess = isGetRequest ? state.allowAnonReads : state.allowAnonWrites;
// Get permission record
const permission = sqlTiddlerDatabase.getPermissionByName(permissionName);
// ACL Middleware will only apply if the entity has a middleware record
if(aclRecord && aclRecord?.permission_id === permission?.permission_id) {
// If not authenticated and anonymous access is not allowed, request authentication
if(!state.authenticatedUsername && !state.allowAnon) {
if(state.urlInfo.pathname !== '/login') {
redirectToLogin(response, request.url);
return;
}
}
// Check if user is authenticated
if(!state.authenticatedUser && !hasAnonymousAccess && !response.headersSent) {
response.writeHead(401, "Unauthorized");
response.end();
return;
}
// Check ACL permission
var hasPermission = request.method === "POST" || sqlTiddlerDatabase.checkACLPermission(state.authenticatedUser.user_id, entityType, decodedEntityName, permissionName)
if(!hasPermission && !hasAnonymousAccess) {
var entity = sqlTiddlerDatabase.getEntityByName(entityType, decodedEntityName);
if(entity?.owner_id) {
if(state.authenticatedUser?.user_id !== entity.owner_id) {
if(!response.headersSent) {
response.writeHead(403, "Forbidden");
response.end();
}
return;
}
} else {
// Get permission record
const permission = sqlTiddlerDatabase.getPermissionByName(permissionName);
// ACL Middleware will only apply if the entity has a middleware record
if(aclRecord && aclRecord?.permission_id === permission?.permission_id) {
// If not authenticated and anonymous access is not allowed, request authentication
if(!state.authenticatedUsername && !state.allowAnon) {
if(state.urlInfo.pathname !== '/login') {
redirectToLogin(response, request.url);
return;
}
}
// Check if user is authenticated
if(!state.authenticatedUser && !hasAnonymousAccess && !response.headersSent) {
response.writeHead(401, "Unauthorized");
response.end();
return;
}
// Check ACL permission
var hasPermission = request.method === "POST" || sqlTiddlerDatabase.checkACLPermission(state.authenticatedUser.user_id, entityType, decodedEntityName, permissionName)
if(!hasPermission && !hasAnonymousAccess) {
if(!response.headersSent) {
response.writeHead(403, "Forbidden");
response.end();
}
return;
}
}
}
};

View File

@ -137,7 +137,9 @@ SqlTiddlerDatabase.prototype.createTables = function() {
CREATE TABLE IF NOT EXISTS recipes (
recipe_id INTEGER PRIMARY KEY AUTOINCREMENT,
recipe_name TEXT UNIQUE NOT NULL,
description TEXT NOT NULL
description TEXT NOT NULL,
owner_id INTEGER,
FOREIGN KEY (owner_id) REFERENCES users(user_id)
)
`,`
-- ...and recipes also have an ordered list of bags
@ -291,6 +293,18 @@ SqlTiddlerDatabase.prototype.createRecipe = function(recipe_name,bag_names,descr
return updateRecipes.lastInsertRowid;
};
/*
Assign a recipe to a user
*/
SqlTiddlerDatabase.prototype.assignRecipeToUser = function(recipe_name,user_id) {
this.engine.runStatement(`
UPDATE recipes SET owner_id = $user_id WHERE recipe_name = $recipe_name
`,{
$recipe_name: recipe_name,
$user_id: user_id
});
};
/*
Returns {tiddler_id:}
*/
@ -486,6 +500,18 @@ SqlTiddlerDatabase.prototype.getRecipeTiddler = function(title,recipe_name) {
Checks if a user has permission to access a recipe
*/
SqlTiddlerDatabase.prototype.hasRecipePermission = function(userId, recipeName, permissionName) {
// check if the user is the owner of the entity
const recipe = this.engine.runStatementGet(`
SELECT owner_id
FROM recipes
WHERE recipe_name = $recipe_name
`, {
$recipe_name: recipeName
});
if(recipe?.owner_id) {
return recipe.owner_id === userId;
}
return this.checkACLPermission(userId, "recipe", recipeName, permissionName)
};
@ -556,7 +582,7 @@ SqlTiddlerDatabase.prototype.checkACLPermission = function(userId, entityType, e
$permission_id: aclRecord.permission_id
});
const hasPermission = result !== undefined;
let hasPermission = result !== undefined;
return hasPermission;
};
@ -578,6 +604,19 @@ SqlTiddlerDatabase.prototype.getEntityAclRecords = function(entityName) {
return aclRecords
}
/*
Get the entity by name
*/
SqlTiddlerDatabase.prototype.getEntityByName = function(entityType, entityName) {
const entityInfo = this.entityTypeToTableMap[entityType];
if (entityInfo) {
return this.engine.runStatementGet(`SELECT * FROM ${entityInfo.table} WHERE ${entityInfo.column} = $entity_name`, {
$entity_name: entityName
});
}
return null;
}
/*
Get the titles of the tiddlers in a bag. Returns an empty array for bags that do not exist
*/