Adding new realm security functions

(Any discrepancies should be edited, though *most* of this should be accurate, but how permissions cascade can be confusing i.e. user permissions = !user.template + !user.template.site Reference)

Intro

Because this information appears to be in various places or incomplete, this page will attempt to give an overview to links about how you would go about adding new security functions to your tool code and customizing them in the admin section. There are also a few methods of backfilling the permissions to existing sites since if you change the !site.template.* realms, they only apply to new sites. Note that site realm functions apply differently from user and group realm functions which are calculated dynamically and not applied to sites statically. (Fill out more details about this: Here's some good info: Permissions In-Depth, Configuring Sakai)

If you add a new security function intended to be related to a site, it will only be added to new sites created after this function was added. Additionally if you add a tool (from contrib or other sources) that has security functions, these will work the same way.

Adding new security function

Adding and using a new security function is pretty easy. You either registerFunction in your code in the FunctionManager (Using the FunctionManager Service) or you can register a function in XML. See the Sakai Security doc Sakai Security .doc for full details.

Once you have it registered, you can use the SecurityService (Using the SecurityService) to check your function. However, as mentioned they will only appear in new sites. This discussion came up on the mailing lists on 06/11. (How to register a new funciton : Nabble)

Adding security function to existing sites (backfill)

There are a number of ways to do this depending on how automated you want it for your users. When you change the functions on !site.template.course for instance, it will only apply to all newly course sites as this is a template realm. You will have to run one of these methods to backfill it. You can either use the site.helper realm, a tool, SQL conversion scripts or web services.

!site.helper

If you have a simple case where you're adding new functions to existing roles and you don't need the end user to be able to adjust these for a period of time, you should be able to use the !site.helper template realm. If you add your function to the correct roles in this template, it will be overridden in any sites. See this documentation on this for more information. Site Helper Realm

Using a tool

The admin site permission updater sounds like a popular tool for doing it if you're the one doing the updating. This tool has to be built from source, but can be found here: 

Old 2.6/2.7/2.8 version: https://source.sakaiproject.org/contrib/caret/admin-site-perms/trunk/

This is planned as a default tool in 2.10: https://source.sakaiproject.org/svn//site/trunk/admin-perms-tool/

For 2.9 because of SAK-25261 it doesn't build directly, but here is a separate branch for 2.9: https://source.sakaiproject.org/svn/site/branches/admin-perms-tool-2.9.x

SQL Scripts (pattern)

Backfilling permissions can also be done with SQL scripts, and this is how they are automated in conversion scripts. It's pretty long, but the pattern is pretty easy to follow.

For instance here is the 2.6 conversion scripts for the site.roleswap backfill related to SAK-12176. This adds the function "msg.emailout" and fills it to the specified roles. The only part that the user has to define is the "INSERT INTO", the rest is all copy/paste generally, unless you want to avoid specific realms. 

Mysql version. The related version for Oracle is very similar and is in https://source.sakaiproject.org/svn/reference/trunk/docs/conversion/sakai_2_6_0_oracle_conversion.sql

-- for each realm that has a role matching something in this table, we will add to that role the function from this table
CREATE TABLE PERMISSIONS_SRC_TEMP (ROLE_NAME VARCHAR(99), FUNCTION_NAME VARCHAR(99));


-- Customize these in with the ROLE_NAME's and FUNCTION_NAME's you need to fill
INSERT INTO PERMISSIONS_SRC_TEMP values ('maintain','msg.emailout');
INSERT INTO PERMISSIONS_SRC_TEMP values ('Instructor','msg.emailout');
INSERT INTO PERMISSIONS_SRC_TEMP values ('CIG Coordinator','msg.emailout');
INSERT INTO PERMISSIONS_SRC_TEMP values ('Program Coordinator','msg.emailout');
INSERT INTO PERMISSIONS_SRC_TEMP values ('Program Admin','msg.emailout');


-- You shouldn't need to change anything below this unless you want to exclude certain realms
-- lookup the role and function numbers
CREATE TABLE PERMISSIONS_TEMP (ROLE_KEY INTEGER, FUNCTION_KEY INTEGER);
INSERT INTO PERMISSIONS_TEMP (ROLE_KEY, FUNCTION_KEY)
SELECT SRR.ROLE_KEY, SRF.FUNCTION_KEY
from PERMISSIONS_SRC_TEMP TMPSRC
JOIN SAKAI_REALM_ROLE SRR ON (TMPSRC.ROLE_NAME = SRR.ROLE_NAME)
JOIN SAKAI_REALM_FUNCTION SRF ON (TMPSRC.FUNCTION_NAME = SRF.FUNCTION_NAME);

-- insert the new functions into the roles of any existing realm that has the role (don't convert the "!site.helper")
INSERT INTO SAKAI_REALM_RL_FN (REALM_KEY, ROLE_KEY, FUNCTION_KEY)
SELECT
    SRRFD.REALM_KEY, SRRFD.ROLE_KEY, TMP.FUNCTION_KEY
FROM
    (SELECT DISTINCT SRRF.REALM_KEY, SRRF.ROLE_KEY FROM SAKAI_REALM_RL_FN SRRF) SRRFD
    JOIN PERMISSIONS_TEMP TMP ON (SRRFD.ROLE_KEY = TMP.ROLE_KEY)
    JOIN SAKAI_REALM SR ON (SRRFD.REALM_KEY = SR.REALM_KEY)
    WHERE SR.REALM_ID != '!site.helper'
    AND NOT EXISTS (
        SELECT 1
            FROM SAKAI_REALM_RL_FN SRRFI
            WHERE SRRFI.REALM_KEY=SRRFD.REALM_KEY AND SRRFI.ROLE_KEY=SRRFD.ROLE_KEY AND SRRFI.FUNCTION_KEY=TMP.FUNCTION_KEY
    );

-- clean up the temp tables
DROP TABLE PERMISSIONS_TEMP;
DROP TABLE PERMISSIONS_SRC_TEMP;
WebServices

A writeup on using Webservices to do this is available here from Steve Swinsburg.