js: Move app delete to C.
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build Tilde Friends / Build-All (push) Successful in 14m34s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build Tilde Friends / Build-All (push) Successful in 14m34s
				
			This commit is contained in:
		| @@ -39,6 +39,7 @@ const int64_t k_refresh_interval = 1ULL * 7 * 24 * 60 * 60 * 1000; | ||||
|  | ||||
| static JSValue _authenticate_jwt(tf_ssb_t* ssb, JSContext* context, const char* jwt); | ||||
| static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv); | ||||
| static bool _is_name_valid(const char* name); | ||||
| static const char* _make_session_jwt(JSContext* context, tf_ssb_t* ssb, const char* name); | ||||
| static const char* _make_set_session_cookie_header(tf_http_request_t* request, const char* session_cookie); | ||||
| const char** _form_data_decode(const char* data, int length); | ||||
| @@ -1081,6 +1082,89 @@ static void _httpd_endpoint_view(tf_http_request_t* request) | ||||
| 	tf_ssb_run_work(ssb, _httpd_endpoint_view_work, _httpd_endpoint_view_after_work, view); | ||||
| } | ||||
|  | ||||
| typedef struct _delete_t | ||||
| { | ||||
| 	tf_http_request_t* request; | ||||
| 	const char* session; | ||||
| 	int response; | ||||
| } delete_t; | ||||
|  | ||||
| static void _httpd_endpoint_delete_work(tf_ssb_t* ssb, void* user_data) | ||||
| { | ||||
| 	delete_t* delete = user_data; | ||||
| 	tf_http_request_t* request = delete->request; | ||||
|  | ||||
| 	JSMallocFunctions funcs = { 0 }; | ||||
| 	tf_get_js_malloc_functions(&funcs); | ||||
| 	JSRuntime* runtime = JS_NewRuntime2(&funcs, NULL); | ||||
| 	JSContext* context = JS_NewContext(runtime); | ||||
|  | ||||
| 	JSValue jwt = _authenticate_jwt(ssb, context, delete->session); | ||||
| 	JSValue user = JS_GetPropertyStr(context, jwt, "name"); | ||||
| 	const char* user_string = JS_ToCString(context, user); | ||||
| 	if (user_string && _is_name_valid(user_string)) | ||||
| 	{ | ||||
| 		size_t length = strlen(user_string); | ||||
| 		if (request->path && request->path[0] == '/' && request->path[1] == '~' && | ||||
| 			/* TODO: admin users used to be able to delete core apps */ | ||||
| 			strncmp(request->path + 2, user_string, length) == 0 && request->path[2 + length] == '/') | ||||
| 		{ | ||||
| 			char* app_name = tf_strdup(request->path + 2 + length + 1); | ||||
| 			if (app_name) | ||||
| 			{ | ||||
| 				if (strlen(app_name) > strlen("/delete") && strcmp(app_name + strlen(app_name) - strlen("/delete"), "/delete") == 0) | ||||
| 				{ | ||||
| 					app_name[strlen(app_name) - strlen("/delete")] = '\0'; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			size_t path_length = strlen("path:") + strlen(app_name) + 1; | ||||
| 			char* app_path = tf_malloc(path_length); | ||||
| 			snprintf(app_path, path_length, "path:%s", app_name); | ||||
|  | ||||
| 			bool changed = false; | ||||
| 			changed = tf_ssb_db_remove_value_from_array_property(ssb, user_string, "apps", app_name) || changed; | ||||
| 			changed = tf_ssb_db_remove_property(ssb, user_string, app_path) || changed; | ||||
| 			delete->response = changed ? 200 : 404; | ||||
| 			tf_free(app_name); | ||||
| 			tf_free(app_path); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		delete->response = 401; | ||||
| 	} | ||||
|  | ||||
| 	JS_FreeCString(context, user_string); | ||||
| 	JS_FreeValue(context, user); | ||||
| 	JS_FreeValue(context, jwt); | ||||
| 	JS_FreeContext(context); | ||||
| 	JS_FreeRuntime(runtime); | ||||
| } | ||||
|  | ||||
| static void _httpd_endpoint_delete_after_work(tf_ssb_t* ssb, int status, void* user_data) | ||||
| { | ||||
| 	delete_t* delete = user_data; | ||||
| 	const char* k_payload = tf_http_status_text(delete->response ? delete->response : 404); | ||||
| 	tf_http_respond(delete->request, delete->response ? delete->response : 404, NULL, 0, k_payload, strlen(k_payload)); | ||||
| 	tf_http_request_unref(delete->request); | ||||
| 	tf_free((void*)delete->session); | ||||
| 	tf_free(delete); | ||||
| } | ||||
|  | ||||
| static void _httpd_endpoint_delete(tf_http_request_t* request) | ||||
| { | ||||
| 	tf_http_request_ref(request); | ||||
| 	tf_task_t* task = request->user_data; | ||||
| 	tf_ssb_t* ssb = tf_task_get_ssb(task); | ||||
| 	delete_t* delete = tf_malloc(sizeof(delete_t)); | ||||
| 	*delete = (delete_t) { | ||||
| 		.request = request, | ||||
| 		.session = tf_http_get_cookie(tf_http_request_get_header(request, "cookie"), "session"), | ||||
| 	}; | ||||
| 	tf_ssb_run_work(ssb, _httpd_endpoint_delete_work, _httpd_endpoint_delete_after_work, delete); | ||||
| } | ||||
|  | ||||
| static void _httpd_endpoint_root_callback(const char* path, void* user_data) | ||||
| { | ||||
| 	tf_http_request_t* request = user_data; | ||||
| @@ -1402,7 +1486,7 @@ static JSValue _authenticate_jwt(tf_ssb_t* ssb, JSContext* context, const char* | ||||
| static bool _session_is_authenticated_as_user(JSContext* context, JSValue session) | ||||
| { | ||||
| 	bool result = false; | ||||
| 	JSValue user = JS_GetPropertyStr(context, session, "user"); | ||||
| 	JSValue user = JS_GetPropertyStr(context, session, "name"); | ||||
| 	const char* user_string = JS_ToCString(context, user); | ||||
| 	result = user_string && strcmp(user_string, "guest") != 0; | ||||
| 	JS_FreeCString(context, user_string); | ||||
| @@ -1813,6 +1897,7 @@ void tf_httpd_register(JSContext* context) | ||||
| 	tf_http_add_handler(http, "/~*/*/", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256/", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/*/view", _httpd_endpoint_view, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~*/*/delete", _httpd_endpoint_delete, NULL, task); | ||||
|  | ||||
| 	tf_http_add_handler(http, "/robots.txt", _httpd_endpoint_robots_txt, NULL, NULL); | ||||
| 	tf_http_add_handler(http, "/debug", _httpd_endpoint_debug, NULL, task); | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/ssb.db.c
									
									
									
									
									
								
							| @@ -1787,6 +1787,44 @@ bool tf_ssb_db_set_property(tf_ssb_t* ssb, const char* id, const char* key, cons | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| bool tf_ssb_db_remove_property(tf_ssb_t* ssb, const char* id, const char* key) | ||||
| { | ||||
| 	bool result = false; | ||||
| 	sqlite3* db = tf_ssb_acquire_db_writer(ssb); | ||||
| 	sqlite3_stmt* statement = NULL; | ||||
| 	if (sqlite3_prepare(db, "DELETE FROM properties WHERE id = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK) | ||||
| 	{ | ||||
| 		if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, -1, NULL) == SQLITE_OK) | ||||
| 		{ | ||||
| 			result = sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) != 0; | ||||
| 		} | ||||
| 		sqlite3_finalize(statement); | ||||
| 	} | ||||
| 	tf_ssb_release_db_writer(ssb, db); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| bool tf_ssb_db_remove_value_from_array_property(tf_ssb_t* ssb, const char* id, const char* key, const char* value) | ||||
| { | ||||
| 	bool result = false; | ||||
| 	sqlite3* db = tf_ssb_acquire_db_writer(ssb); | ||||
| 	sqlite3_stmt* statement = NULL; | ||||
| 	if (sqlite3_prepare(db, | ||||
| 			"UPDATE properties SET value = json_remove(properties.value, entry.fullkey) FROM json_each(properties.value) AS entry WHERE properties.id = ? AND properties.key = ? " | ||||
| 			"AND entry.value = ?", | ||||
| 			-1, &statement, NULL) == SQLITE_OK) | ||||
| 	{ | ||||
| 		if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, -1, NULL) == SQLITE_OK && | ||||
| 			sqlite3_bind_text(statement, 3, value, -1, NULL) == SQLITE_OK) | ||||
| 		{ | ||||
| 			result = sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) != 0; | ||||
| 		} | ||||
| 		sqlite3_finalize(statement); | ||||
| 	} | ||||
| 	tf_ssb_release_db_writer(ssb, db); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| bool tf_ssb_db_identity_get_active(sqlite3* db, const char* user, const char* package_owner, const char* package_name, char* out_identity, size_t out_identity_size) | ||||
| { | ||||
| 	sqlite3_stmt* statement = NULL; | ||||
|   | ||||
							
								
								
									
										19
									
								
								src/ssb.db.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/ssb.db.h
									
									
									
									
									
								
							| @@ -399,6 +399,25 @@ const char* tf_ssb_db_get_property(tf_ssb_t* ssb, const char* id, const char* ke | ||||
| */ | ||||
| bool tf_ssb_db_set_property(tf_ssb_t* ssb, const char* id, const char* key, const char* value); | ||||
|  | ||||
| /** | ||||
| ** Remove an entry in the properties table. | ||||
| ** @param ssb The SSB instance. | ||||
| ** @param id The user. | ||||
| ** @param key The property key. | ||||
| ** @return true if the property was removed successfully. | ||||
| */ | ||||
| bool tf_ssb_db_remove_property(tf_ssb_t* ssb, const char* id, const char* key); | ||||
|  | ||||
| /** | ||||
| ** Remove a value from an entry in the properties table that is a JSON array. | ||||
| ** @param ssb The SSB instance. | ||||
| ** @param id The user. | ||||
| ** @param key The property key. | ||||
| ** @param value The value to remove from the JSON array. | ||||
| ** @return true if the property was updated. | ||||
| */ | ||||
| bool tf_ssb_db_remove_value_from_array_property(tf_ssb_t* ssb, const char* id, const char* key, const char* value); | ||||
|  | ||||
| /** | ||||
| ** Resolve a hostname to its index path by global settings. | ||||
| ** @param ssb The SSB instance. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user