Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Setting gsh.useLegacy = true in grouper.properties.
  • Using a command line argument  (gsh.sh -forceLegacyGsh)

GrouperShell is for Grouper admins.  End users can script with the grouper client command line utility

Escape

Escape things in groovysh with single backslash.  e.g.

...

Code Block
languagegroovy
titleAdd a new type with an attribute, add this to group and then set its value on the group, e.g.
grouperSession = GrouperSession.startRootSession();
g = GroupFinder.findByName(sessiongrouperSession, "admin:loader_groups");
type = typeAdd("sync_group");
type.addAttribute(sessiongrouperSession, "sync_group", false, "sync");
groupAddType("admin:loader_groups", "sync_group");
g.setAttribute("sync", "true");

...

Command

Description

addComposite(group name, composite type, left group name, right group name)

Add composite membership.  e.g. CompositeType.UNION

addMember(group name, subject id)

Add member to the members list for the group.

addMember(group name, subject id, field)

Add member to the specified list for the group.

delComposite(group name)

Delete composite membership from group

delMember(group name, subject id)

Delete member from the members list for the group

delMember(group name, subject id, field)

Delete member from the specified list for the group

getMembers(group name)

Get members of group

hasMember(group name, subject id)

Check whether subject is member of the members list

hasMember(group name, subject id, field)

Check whether subject is member of the specified list

Privileges

GrouperSession grouperSession = GrouperSession.startRootSession();
Group group = GroupFinder.findByName(grouperSession, "a:b:c", true);
group.addMember(SubjectFinder.findByIdAndSource("someId", "sourceId", true), false);
Add member with subjectId and sourceId
GrouperSession grouperSession = GrouperSession.startRootSession();
Group group = GroupFinder.findByName(grouperSession, "a:b:c", true);
group.addMember(SubjectFinder.findByIdentifierAndSource("someIdentifier", "sourceId", true), false);
Add member with subjectIdentifier and sourceId

Privileges

Command

Description

grantPriv(group name, subject id, privilege)

Grant privilege on group. privilege must be an AccessPrivilege (e.g. AccessPrivilege.ADMIN)

grantPriv(stem name

Command

Description

grantPriv(group name, subject id, privilege)

Grant privilege on group. privilege must be an AccessPrivilege (e.g. AccessPrivilege.ADMIN)

grantPriv(stem name, subject id, privilege)

Grant privilege on stem. privilege must be a NamingPrivilege (e.g. NamingPrivilege.STEM)

hasPriv(group name, subject id, privilege)

Grant privilege on stem. privilege must be a NamingPrivilege (e.g. NamingPrivilege.STEM)

hasPriv(group name, subject id, privilege)

Check whether subject has privilege on group. privilege must be an AccessPrivilege (e.g. AccessPrivilege.ADMIN)

hasPriv(stem name, subject id, privilege)

Check whether subject has privilege on strem. privilege must be a NamingPrivilege (e.g. NamingPrivilege.STEM)

revokePriv(group name, subject id, privilege)

Revoke privilege on group. privilege must be an AccessPrivilege (e.g. AccessPrivilege.ADMIN)

revokePriv(stem name, subject id, privilege)

Revoke privilege on stem. privilege must be a NamingPrivilege (e.g. NamingPrivilege.STEM)

...

Delete stem and subcontents

Command

Description

addRootStem(extension, displayExtension)

Add top-level stem to the registry

addStem(parent stem name, extension, displayExtension)

Add stem to registry

delStem(stem name)

Delete stem from registry

obliterateStem(stem name, testOnlyBoolean, deleteFromPointInTimeBoolean)    (Grouper v2.0.2+)

Delete stem, and subobjects.

If testonly (true|false), then only
print a report.  This is not supported when deleteFromPointInTime is true.

If deleteFromPointInTime (true|false), then delete from point in time as well.  Otherwise, point in time records are not deleted.

Note that point in time data can only be deleted after the actual objects have been deleted and those deletions have been processed by the changeLogTempToChangeLog job, which runs once a minute by default with the Grouper Daemon.  So when you call obliterateStem(name, false, true), it will first obliterate the actual stem, then sleep and keep checking if the changeLogTempToChangeLog job has completed.  When it completes, it will obliterate from the point in time data.

GrouperSession must be open before calling...

getStemAttr(stem name, attr)

Get value of stem attribute

getStems(name)

Find all stems with a matching naming attribute value, returns a Set of stems

setStemAttr(stem name, attr, value)

Set value of stem attribute

StemFinder.findByName(grouperSession, name)

Find one stem by name

StemFinder.findByUuid(grouperSession, uuid)

Find one stem by uuid

Delete stem and subcontents


Code Block
grouperSession = GrouperSession.startRootSession();
stem = StemFinder.findByName(grouperSession, "a");
for(child : stem.getChildGroups(Stem.Scope.SUB)) { System.out.println("deleting: " + child.getName()); child.delete();  }
stemList = new ArrayList(stem.getChildStems(Stem.Scope.SUB));
Collections.sort(stemList);
Collections.reverse(stemList);
for(childStem : stemList) { System.out.println("deleting: " + childStem.getName()); childStem.delete(); }
stem.delete();


Subjects

Command

Description

addSubject(id, type, name)

Add local subject to registry. You need the jdbc source for this to work. The type parameter describes the type of subject (e.g. "people"), and is required non-null even though there are few useful api methods to query it.

In 2.4.0.api.41+ patch, this will also create the id, name, description, and loginid attribute (unless grouper.properties create.attributes.when.creating.registry.subjects is false)

RegistrySubject.addOrUpdate(grouperSession, id, type, name, nameAttributeValue, loginid, description, email)In 2.4.0.api.41+ patch, add a registry subject like addSubject, but specify the attribute values of name, loginid, etc
e.g. RegistrySubject.addOrUpdate(grouperSession, "someTestSubject", "person", "Some Testsubject", "Name Some Test Subject", "stsub", "Some Testsubject - employee - also alumni", "some@test.subject");
RegistrySubject.find(id, errorOnNotFound)In 2.4.0.api.41+ patch, get a registry subject
e.g. registrySubject = RegistrySubject.find("someTestSubject", false);
registrySubject.delete(grouperSession)In 2.4.0.api.41+ patch, delete a registry subject
e.g. registrySubject.delete(grouperSession);
RegistrySubjectAttribute.addOrUpdate(subjectId, attributeName, attributeValue)In 2.4.0.api.41+ patch, add or update a registry subject attribute
registrySubjectAttribute.delete()In 2.4.0.api.41+ patch, delete an attribute value

findSubject(idOrIdentifier)

Find a subject by id or identifier

findSubject(idOrIdentifier, type)

Find a subject by id or identifier; type is a deprecated parameter that is ignored

findSubject(idOrIdentifier, type, source)

Find a subject by id or identifier for a specific subject source; type is a deprecated parameter that is ignored

getSources()

Find all Subject sources

grouperSession = GrouperSession.startRootSession();
SubjectFinder.findAll(searchString, source);

Find all subjects in a source by search string

grouperSession = GrouperSession.startRootSession();
SubjectFinder.findByIdAndSource(id, source, exceptionIfNull);
SubjectFinder.findByIdAndSource("12345", "jdbc", true);

Find a subject by id in a certain source

grouperSession = GrouperSession.startRootSession();
SubjectFinder.findByIdentifierAndSource(identifier, source, exceptionIfNull);
SubjectFinder.findByIdentifierAndSource("jsmith", "jdbc", true);

Find a subject by identifier in a certain source

grouperSession = GrouperSession.startRootSession();
SubjectFinder.findByIdOrIdentifierAndSource(idOrIdentifier, source, exceptionIfNull);
SubjectFinder.findByIdOrIdentifierAndSource("jsmith", "jdbc", true);

Find a subject by id or identifier in a certain source

add test subjects to registry (e.g. test.subject.0 through 9)

grouperSession = GrouperSession.startRootSession();
new RegistryReset()._addSubjects();

Edit subject (in this case name)

RegistrySubject registrySubject = GrouperDAOFactory.getFactory().getRegistrySubject().find("user1a", "person", true);
registrySubject.setName("New name");
HibernateSession.byObjectStatic().update(registrySubject);

add a subject application principal with attributes (GSH)


Code Block
String principal = "someApp";
String email = null;

GrouperSession grouperSession = GrouperSession.startRootSession();


addSubject(principal, "application", principal);
HibernateSession.bySqlStatic().executeSql("insert into subjectattribute (subjectId, name, value, searchValue) values (?, ?, ?, ?)", GrouperUtil.toListObject(new Object[]{principal, "description", principal, principal.toLowerCase()}));
if (email != null){ HibernateSession.bySqlStatic().executeSql("insert into subjectattribute (subjectId, name, value, searchValue) values (?, ?, ?, ?)", GrouperUtil.toListObject(new Object[]{principal, "email", email, email.toLowerCase()}));}
HibernateSession.bySqlStatic().executeSql("insert into subjectattribute (subjectId, name, value, searchValue) values (?, ?, ?, ?)", GrouperUtil.toListObject(new Object[]{principal, "loginid", principal, principal}));
HibernateSession.bySqlStatic().executeSql("insert into subjectattribute (subjectId, name, value, searchValue) values (?, ?, ?, ?)", GrouperUtil.toListObject(new Object[]{principal, "name", principal, principal}));



remove a subject with attributes (GSH)


Code Block
String principal = "someApp";
String email = null;

GrouperSession grouperSession = GrouperSession.startRootSession();

HibernateSession.bySqlStatic().executeSql("delete from subjectattribute where subjectId = ?", GrouperUtil.toListObject(new Object[]{principal}));
HibernateSession.bySqlStatic().executeSql("delete from subject where subjectId = ?", GrouperUtil.toListObject(new Object[]{principal}));toListObject(new Object[]{principal}));


subject api diagnostics

grouper.properties (temporarily)

Code Block
gsh.exitOnSubjectCheckConfigProblem = false

gsh

Code Block
GrouperSession.startRootSession();
new edu.internet2.middleware.grouper.grouperUi.serviceLogic.SubjectSourceDiagnostics().assignSourceId("SMUPerson_DEV").assignSubjectId("empl1").assignSubjectIdentifier("netid@school.edu").assignSearchString("em").subjectSourceDiagnosticsFromGsh()
===>
SUCCESS: Found subject by id in 37ms: 'empl1'
         with SubjectFinder.findByIdAndSource("empl1", "SMUPerson_DEV", false)
SUCCESS: Subject id in returned subject matches the subject id searched for: 'empl1'
WARNING: No subject found by identifier in 14ms: 'netid@school.edu'
         with SubjectFinder.findByIdentifierAndSource("netid@school.edu", "SMUPerson_DEV", false)


System

Command

Description

sqlRun(file)

Execute each line of a sql file, just like ant would.  This can run the files generated by registryInitializeSchema()

sqlRun(string)

Executes a single sql statement

:exit

Terminate shell

help()

Display usage information

p(command)

Pretty print results.

:quit

Terminate shell

version()

Return version information

...

Command

Description

help("transaction")

print help information

transactionStatus()

print the list of nested transactions

transactionStart("<GrouperTransactionType>")

start a transaction, or make sure one is already started
   Can use: "READONLY_OR_USE_EXISTING", "NONE", "READONLY_NEW",
"READ_WRITE_OR_USE_EXISTING", "READ_WRITE_NEW"

transactionCommit("<GrouperCommitType>")

commit a transaction
   Can use: "COMMIT_NOW", "COMMIT_IF_NEW_TRANSACTION

transactionRollback("<GrouperRollbackType>")

rollback a transaction
    Can use: "ROLLBACK_NOW", "ROLLBACK_IF_NEW_TRANSACTION

transactionEnd()

end a transaction
    Note if it was read/write, and not committed or rolled back, this will commit and end

Daemon

You can schedule daemon jobs (and in UI) in v2.5.23+

Code Block
GrouperSession.startRootSession();
edu.internet2.middleware.grouper.app.loader.GrouperLoader.scheduleJobs();


Loader

Above, it describes how you can kick off the loader in daemon mode.  You can also execute one job with:

...

Code Block
# (1) Print tab-separated summary of all group members, and flags for direct, indirect, or both
# Depending on the results, you could use the data to create a scrutinized list of Ids to delete, then import it and delete in a loop

me = SubjectFinder.findByIdentifierAndSource("my-username", "pid", true);
session = GrouperSession.start(me);
// OR: session = GrouperSession.startRootSession(True)

group = GroupFinder.findByName(session, "tmp:my:group", true);

effectiveMembers = group.getEffectiveMembers();
immediateMembers = group.getImmediateMembers();

System.out.println(String.join("\t", "id", "name", "Effective", "Immediate"));

for (Member m: group.getMembers()) {
    System.out.print(m.getSubject().getId() + "\t" + m.getSubject().getName() + "\t");
    System.out.print(effectiveMembers.contains(m).toString() + "\t");
    System.out.println(immediateMembers.contains(m).toString() + "\t");
}



# (2) Get the immediate and effective members for a specific source ("pid" in this example), intersect them to find the redundant ones
# This has a dryRun flag, so you can test first

sources = new HashSet<Source>()
sources.add(SourceManager.getInstance().getSource("pid"))

effectiveUsers = group.getEffectiveMembers(Group.getDefaultList(), sources, null)
immediateUsers = group.getImmediateMembers(Group.getDefaultList(), sources, null)

# use retainAll() to find the intersection; i.e., users both as effective and immediate member
immediateUsers.retainAll(effectiveUsers)

System.out.println("There are " + immediateUsers.size() + " users having both direct + indirect memberships");

dryRun = true

for (Member m: immediateUsers) {
    if (dryRun) {
        System.out.println("Ok to delete " + m.getSubject().getId());
    } else {
        System.out.println("Deleting " + m.getSubject().getId());
        group.deleteMember(m, false);
    }
}

# (3) Get the groups this subject is a member of. Note that a group is a kind of subject, and has a toSubject() method to convert it.

import edu.internet2.middleware.grouper.membership.MembershipSubjectContainer

GrouperSession grouperSession = GrouperSession.startRootSession();

Group group = GroupFinder.findByName(grouperSession, "test:testGroup", true);
Subject subject = g.toSubject();

Set<MembershipSubjectContainer> msc = new MembershipFinder().addSubject(subject).findMembershipResult().getMembershipSubjectContainers();

for (MembershipSubjectContainer membershipSubjectContainer : msc) { println(membershipSubjectContainer.getGroupOwner().getName());}

//Note there are a few other options for the search. Add these to the MembershipFinder method chain before calling findMembershipResult():
//  - search immediate, effective, etc. (needs to import MembershipType)
import edu.internet2.middleware.grouper.membership.MembershipType
membershipFinder.assignMembershipType(MembershipType.IMMEDIATE) // options are IMMEDIATE|NONIMMEDIATE|EFFECTIVE|COMPOSITE
//  - retrieve specific groups based on pattern
membershipFinder.assignScope("%:test:%")
//  - Enabled status -- true means enabled only, false, means disabled only, and null means all
membershipFinder.assignEnabled(false)
// For other methods, refer to the Javadoc at httphttps://software.internet2.github.ioedu/grouper/doc/master/grouper-parent/apidocs/index.html?edu/internet2/middleware/grouper/MembershipFinder.html

...

Code Block
languagejava
gcDbAccess = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess();
// "loaderConnection" is the string used in the grouper-loader.properties ( Example: db.warehouse.url --> "warehouse")
gcDbAccess.connectionName("loaderConnection""warehouse")
gcDbAccess.connectionName("loaderConnection").sql("select count(1) from test1").select(int.class);


Code Block
List results = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess().sql("select count(1)name, id from test1grouper_groups").selectselectList(int.class);Object[].class);
for (Object[] row : results) { System.out.println(row[0] + ", " + row[1]);}


See the WIKI for running the Grouper Report manually

...

Code Block
gcDbAccess = new edu.internet2.middleware.grouperClient.jdbc.GcDbAccess();
gcDbAccess.connectionName("warehouse").sql("select count(1) from grouper_groups").select(int.class);


Set password using Grouper built-in authentication

Code Block
v2.5.29+
new GrouperPasswordSave().assignApplication(GrouperPassword.Application.UI).assignUsername("username").assignPassword("password").save();