forked from cory/tildefriends
		
	A brave new world where admin users can use the server identity.
This commit is contained in:
		
							
								
								
									
										21
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/ssb.db.c
									
									
									
									
									
								
							| @@ -1946,3 +1946,24 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id) | ||||
| 	} | ||||
| 	return verified; | ||||
| } | ||||
|  | ||||
| bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, const char* id, const char* permission) | ||||
| { | ||||
| 	bool has_permission = false; | ||||
| 	sqlite3* db = tf_ssb_acquire_db_reader(ssb); | ||||
| 	sqlite3_stmt* statement = NULL; | ||||
| 	if (sqlite3_prepare(db, | ||||
| 			"SELECT COUNT(*) FROM properties, json_each(properties.value -> 'permissions' -> ?) AS permission WHERE properties.id = 'core' AND properties.key = 'settings' AND " | ||||
| 			"permission.value = ?", | ||||
| 			-1, &statement, NULL) == SQLITE_OK) | ||||
| 	{ | ||||
| 		if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, permission, -1, NULL) == SQLITE_OK && | ||||
| 			sqlite3_step(statement) == SQLITE_ROW) | ||||
| 		{ | ||||
| 			has_permission = sqlite3_column_int64(statement, 0) > 0; | ||||
| 		} | ||||
| 		sqlite3_finalize(statement); | ||||
| 	} | ||||
| 	tf_ssb_release_db_reader(ssb, db); | ||||
| 	return has_permission; | ||||
| } | ||||
|   | ||||
| @@ -416,6 +416,15 @@ void tf_ssb_db_resolve_index_async(tf_ssb_t* ssb, const char* host, void (*callb | ||||
| */ | ||||
| bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id); | ||||
|  | ||||
| /** | ||||
| ** Check if a user has a specific permission. | ||||
| ** @param ssb The SSB instance. | ||||
| ** @param id The user ID. | ||||
| ** @param permission The name of the permission. | ||||
| ** @return true If the user has the requested permission. | ||||
| */ | ||||
| bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, const char* id, const char* permission); | ||||
|  | ||||
| /** | ||||
| ** An SQLite authorizer callback.  See https://www.sqlite.org/c3ref/set_authorizer.html for use. | ||||
| ** @param user_data User data registered with the authorizer. | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/ssb.js.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/ssb.js.c
									
									
									
									
									
								
							| @@ -381,6 +381,14 @@ static void _tf_ssb_getIdentities_visit(const char* identity, void* user_data) | ||||
| static void _tf_ssb_get_identities_work(tf_ssb_t* ssb, void* user_data) | ||||
| { | ||||
| 	identities_visit_t* work = user_data; | ||||
| 	if (tf_ssb_db_user_has_permission(ssb, work->user, "administration")) | ||||
| 	{ | ||||
| 		char id[k_id_base64_len] = ""; | ||||
| 		if (tf_ssb_whoami(ssb, id, sizeof(id))) | ||||
| 		{ | ||||
| 			_tf_ssb_getIdentities_visit(*id == '@' ? id + 1 : id, work); | ||||
| 		} | ||||
| 	} | ||||
| 	tf_ssb_db_identity_visit(ssb, work->user, _tf_ssb_getIdentities_visit, user_data); | ||||
| } | ||||
|  | ||||
| @@ -445,6 +453,10 @@ static void _tf_ssb_get_private_key_work(tf_ssb_t* ssb, void* user_data) | ||||
| { | ||||
| 	get_private_key_t* work = user_data; | ||||
| 	work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key)); | ||||
| 	if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, work->user, "administration")) | ||||
| 	{ | ||||
| 		work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void _tf_ssb_get_private_key_after_work(tf_ssb_t* ssb, int status, void* user_data) | ||||
| @@ -625,6 +637,14 @@ static void _tf_ssb_getIdentityInfo_visit(const char* identity, void* data) | ||||
| static void _tf_ssb_getIdentityInfo_work(tf_ssb_t* ssb, void* user_data) | ||||
| { | ||||
| 	identity_info_work_t* request = user_data; | ||||
| 	if (tf_ssb_db_user_has_permission(ssb, request->name, "administration")) | ||||
| 	{ | ||||
| 		char id[k_id_base64_len] = ""; | ||||
| 		if (tf_ssb_whoami(ssb, id, sizeof(id))) | ||||
| 		{ | ||||
| 			_tf_ssb_getIdentityInfo_visit(*id == '@' ? id + 1 : id, request); | ||||
| 		} | ||||
| 	} | ||||
| 	tf_ssb_db_identity_visit(ssb, request->name, _tf_ssb_getIdentityInfo_visit, request); | ||||
|  | ||||
| 	sqlite3* db = tf_ssb_acquire_db_reader(ssb); | ||||
| @@ -777,6 +797,10 @@ static void _tf_ssb_append_message_with_identity_get_key_work(tf_ssb_t* ssb, voi | ||||
| { | ||||
| 	append_message_t* work = user_data; | ||||
| 	work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, work->user, work->id, work->private_key, sizeof(work->private_key)); | ||||
| 	if (!work->got_private_key && tf_ssb_db_user_has_permission(ssb, work->user, "administration")) | ||||
| 	{ | ||||
| 		work->got_private_key = tf_ssb_db_identity_get_private_key(ssb, ":admin", work->id, work->private_key, sizeof(work->private_key)); | ||||
| 	} | ||||
| 	tf_ssb_db_get_latest_message_by_author(ssb, work->id, &work->previous_sequence, work->previous_id, sizeof(work->previous_id)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -25,6 +25,30 @@ try: | ||||
| 	#options.add_argument('--headless') | ||||
| 	driver = webdriver.Firefox(options = options, service = service) | ||||
| 	wait = WebDriverWait(driver, 10) | ||||
|  | ||||
| 	driver.get('http://localhost:8888') | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-navigation').shadow_root.find_element(By.LINK_TEXT, 'login').click() | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'register_label').click() | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'name').send_keys('adminuser') | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'password').send_keys('admin_password') | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'confirm').send_keys('admin_password') | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'loginButton').click() | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'document'))) | ||||
| 	driver.switch_to.frame(driver.find_element(By.ID, 'document')) | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.LINK_TEXT, 'identity'))) | ||||
| 	driver.switch_to.default_content() | ||||
|  | ||||
| 	driver.get('http://localhost:8888/~core/admin/') | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'document'))) | ||||
| 	driver.switch_to.frame(driver.find_element(By.ID, 'document')) | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'gs_room_name'))).send_keys('test room') | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.XPATH, '//*[@id="gs_room_name"]/following-sibling::button'))).click() | ||||
| 	driver.switch_to.alert.accept() | ||||
| 	driver.switch_to.default_content() | ||||
|  | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-navigation').shadow_root.find_element(By.ID, 'identity').click() | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-navigation').shadow_root.find_element(By.ID, 'logout').click() | ||||
|  | ||||
| 	driver.get('http://localhost:8888') | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-navigation').shadow_root.find_element(By.LINK_TEXT, 'login').click() | ||||
| 	driver.find_element(By.TAG_NAME, 'tf-auth').shadow_root.find_element(By.ID, 'register_label').click() | ||||
| @@ -82,13 +106,6 @@ try: | ||||
| 	driver.switch_to.frame(wait.until(expected_conditions.presence_of_element_located((By.ID, 'document')))) | ||||
| 	id1 = wait.until(expected_conditions.presence_of_element_located((By.TAG_NAME, 'li'))).text.split(' ')[-1] | ||||
|  | ||||
| 	driver.get('http://localhost:8888/~core/admin/') | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'document'))) | ||||
| 	driver.switch_to.frame(driver.find_element(By.ID, 'document')) | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'gs_room_name'))).send_keys('test room') | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.XPATH, '//*[@id="gs_room_name"]/following-sibling::button'))).click() | ||||
| 	driver.switch_to.alert.accept() | ||||
|  | ||||
| 	driver.get('http://localhost:8888') | ||||
| 	wait.until(expected_conditions.presence_of_element_located((By.ID, 'document'))) | ||||
| 	driver.switch_to.frame(driver.find_element(By.ID, 'document')) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user