Forum OpenACS Development: Response to Group definitions and use
Posted by
Andrew Piskorski
on 09/27/01 11:49 PM
Nick, there are several obvious ways of creating ACS users and groups
which work, but which don't do everything the ACS expects.
For example, you need to use acs.add_user(), not acs_user.new().
Naturally, the differences between these various functions are not
documented. Your problem is probably that you did the obvious thing,
which left out some fiddly step that the ACS assumes was done.
Your best bet is to look carefully at the existing ACS login and admin pages that create users and groups, and do it the same way.
But for comparison, here's some Oracle PL/SQL code that I used in testing an ACS 4.2 site. If I remember correctly, this code creates users and groups exactly the same way as the ACS 4.2 UI pages do, and it also expunges them from the system cleanly and completely. (I don't know if any of this low level user/group stuff has been changed for OpenACS 4, but I suspect not.)
Creates a test user and group:
declare v_group_id integer; v_person_id integer; v_rel_id integer; begin -- Create company A: v_group_id := p_account.new( v_account_code => 'A' ,v_context_id => p_const.package_id_is ); v_person_id := acs.add_user ( email => 'x@a.com', first_names => 'X', last_name => 'X', password => 'X', salt => 'X' ); -- add X into A v_rel_id := membership_rel.new( object_id_one => v_group_id ,object_id_two => v_person_id ); end; / show errors
Deletes the test user and group:
(Now, why this calls acs_group.delete instead of p_account.delete, I don't know. Probably that's a bug.)
declare test_users pl_list.integer_list; test_groups pl_list.integer_list; test_parties pl_list.integer_list; begin select party_id bulk collect into test_users from parties where email in ('x@a.com', 'y@b.com') ; select party_id bulk collect into test_groups from parties where party_id in ( select account_id from p_accounts where account_code in ('A', 'B') ); select party_id bulk collect into test_parties from parties where email in ('x@a.com', 'y@b.com') or party_id in ( select account_id from p_accounts where account_code in ('A', 'B') ); for i in test_groups.first .. test_groups.last loop acs_group.delete(test_groups(i)); -- Note that deleting the group also deletes the membership_rels for -- the group, so we don't have to do it explicitly - imagine that! end loop; for i in test_users.first .. test_users.last loop for j in ( select rel_id from acs_rels where rel_type = 'membership_rel' and object_id_two = test_users(i) ) loop membership_rel.delete(j.rel_id); end loop; delete from acs_permissions p where p.object_id = test_users(i) or p.grantee_id = test_users(i) ; acs_user.delete(test_users(i)); -- Note that acs.remove_user simply delets the row from the users table, -- which is not what we want! end loop; end; / show errors
Some other stuff:
Of course, I'd extended the ACS groups table with a "p_accounts" table, so here's the part that actually calls the ACS group create function:
create or replace package body p_account is function new ( v_account_code in p_accounts.account_code%TYPE -- AKA group_name: ,v_account_pretty_name in groups.group_name%TYPE default null ,v_allow_auto_join_p in p_accounts.allow_auto_join_p%TYPE default 't' ,v_account_id in p_accounts.account_id%TYPE default null ,v_creation_date in acs_objects.creation_date%TYPE default sysdate ,v_creation_user in acs_objects.creation_user%TYPE default null ,v_creation_ip in acs_objects.creation_ip%TYPE default null ,v_context_id in acs_objects.context_id%TYPE default null ) return p_accounts.account_id%TYPE is v_id integer; w_account_pretty_name groups.group_name%TYPE; begin if v_account_pretty_name is null then w_account_pretty_name := v_account_code; else w_account_pretty_name := v_account_pretty_name; end if; v_id := acs_group.new( group_id => v_id ,object_type => 'p_account' ,creation_date => v_creation_date ,creation_user => v_creation_user ,creation_ip => v_creation_ip ,context_id => v_context_id ,group_name => w_account_pretty_name ); insert into p_accounts ( account_id, account_code, address_id ,allow_auto_join_p ) values ( v_id, v_account_code, null ,v_allow_auto_join_p ); return v_id; end new; procedure delete ( v_account_id in p_accounts.account_id%TYPE ) is begin -- Our application logic says that any address mapped directly to the -- account belongs ONLY to that account, so if we're deleting the account -- delete the address too: delete from p_addresses where address_id = ( select address_id from p_accounts where account_id = v_account_id ); delete from p_accounts where account_id = v_account_id; delete from acs_permissions p where p.object_id = v_account_id or p.grantee_id = v_account_id ; acs_group.delete(v_account_id); end delete; end p_account; / show errors