├── Add-Alias
├── README.md
└── addAlias.gs
├── Aggregate-Extract-Sheet
├── Aggregate.gs
├── Extract.gs
└── README.md
├── Attendance-or-MilkCounts
├── README.md
└── code.gs
├── Delta-OU
├── Delta OU.gs
├── README.md
├── gui.gs
└── index.html
├── ES-Student-Update
├── README.md
└── UpdateStudents.gs
├── Groups-and-Group-Members
├── Clear Descriptions.gs
├── Groups and Members.gs
├── README.md
└── Remove Empty Contact Groups.gs
├── HashSpreadsheet
├── README.md
└── hash.gs
├── List-Students-and-Other-Goodies
├── README.md
├── listAllUsers.gs
└── listInactiveStudents.gs
├── OU-2-Group
├── OUs2Group.gs
└── README.md
├── README.md
├── RandomPassword-for-Substitute-Teacher-Accounts
├── Change Password.gs
└── README.md
├── Remove-Aliases
├── README.md
└── Remove Aliases.gs
├── Remove-sites
├── README.md
├── RemoveUser.gs
└── SuspendedUsers.gs
├── State-Abbreviation-converter
└── find-and-replace.gs
├── Suspend-OU
├── README.md
└── Suspend OU.gs
├── Sync-OU-to-Group
├── GetNewUsers.gs
├── ImportGroups.gs
├── ImportUsers.gs
├── README.md
└── SyncGroup.gs
└── Zebra
├── Build-A-Box.gs
├── README.md
├── Triggers.gs
├── importFromGoogle.gs
├── redCard.gs
├── scope.gs
└── updateForm.gs
/Add-Alias/README.md:
--------------------------------------------------------------------------------
1 | Used as part of scripts, not not a stand-alone function. A simple function which adds an alias to a user's account, after checking to see if the alias already exists for that user.
2 | The function test() is proof of concept and an example of usage.
3 |
4 | Requires AdminSDK to be enabled.
5 |
--------------------------------------------------------------------------------
/Add-Alias/addAlias.gs:
--------------------------------------------------------------------------------
1 | function test(){
2 | var email = {primary:"gales@wgsd.us",
3 | alias:"steven.gale@wgsd.us"};
4 | AddAlias(email.primary, email.alias)
5 | }
6 |
7 | function AddAlias(user, alt){
8 | alt = {alias:alt}
9 | var aliases = AdminDirectory.Users.Aliases.list(user)
10 | var numAliases = AdminDirectory.Users.Aliases.list(user).aliases.length
11 | //check if alias exists
12 | var re = new RegExp(alt,"g")
13 | if (re.test(aliases)){
14 | Logger.log("Alias %s exists, skipping",alt)}
15 | else{
16 | var x = AdminDirectory.Users.get(user).aliases.length
17 | AdminDirectory.Users.Aliases.insert(alt, user)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Aggregate-Extract-Sheet/Aggregate.gs:
--------------------------------------------------------------------------------
1 | function aggregate() {
2 | var folder, spreadsheets, combinedSheet
3 | folder = DriveApp.getFoldersByName("Aggregate Spreadsheets");
4 | combinedSheet = SpreadsheetApp.create("Combined Spreadsheets");
5 | while(folder.hasNext()){
6 | spreadsheets = folder.next().getFilesByType(MimeType.GOOGLE_SHEETS);
7 | while(spreadsheets.hasNext()){
8 | var ss, sheet, col, row, values, newRow, range
9 | ss = SpreadsheetApp.open(spreadsheets.next());
10 | sheet = ss.getSheets()[0];
11 | col = sheet.getLastColumn();
12 | row = sheet.getLastRow();
13 | values = sheet.getRange(1, 1, row, col).getValues();
14 | newRow = combinedSheet.getSheets()[0].getLastRow()+1;
15 | Logger.log(newRow)
16 | Logger.log(row)
17 | range = combinedSheet.getSheets()[0].getRange(newRow, 1, (row),col);
18 | range.setValues(values)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Aggregate-Extract-Sheet/Extract.gs:
--------------------------------------------------------------------------------
1 | function extract() {
2 | var ss, sheets, sheet, range
3 | ss = SpreadsheetApp.getActive()
4 | sheets = ss.getSheets()
5 | for (i in sheets){
6 | var row, col
7 | sheet = sheets[i];
8 | row = sheet.getLastRow();
9 | col = sheet.getLastColumn();
10 | range = sheet.getRange(1,1,row,col);
11 | var values = range.getValues();
12 | var name = sheet.getRange("C3").getValue();
13 |
14 | SpreadsheetApp.create(name)
15 | .getSheets()[0].activate()
16 | .getRange(1,1,row,col)
17 | .setValues(values);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Aggregate-Extract-Sheet/README.md:
--------------------------------------------------------------------------------
1 | Simple scripts used to either pull together sheets within a folder into 1 Master Sheet (**Aggregate**) or take each sheet in a Workbook and copy it's values to a newly created individual Workbook (**Extract**).
2 |
--------------------------------------------------------------------------------
/Attendance-or-MilkCounts/README.md:
--------------------------------------------------------------------------------
1 | Associate with a Google Sheet that has one Sheet per Class. Every Sheet will become an Answer in a Dropdown item in the Google Form. When that Answer is chosen, the next page will be the names listed in the first column of the page.
2 | Changing the Spreadsheet will update the Form when the trigger is installed.
3 |
4 | We use this in conjunction with FormMule/CopyDown to email our Milk Count numbers to the cafeteria on a daily basis. There is a summary email which is set on a daily trigger and a onSubmit() trigger which mails the inidvidual Teachers responses to the cafeteria staff when a form is filled out (because they wanted it that way).
5 |
--------------------------------------------------------------------------------
/Attendance-or-MilkCounts/code.gs:
--------------------------------------------------------------------------------
1 | var ss = SpreadsheetApp.openById("CLASS_ROSTER_SPREADSHEET_ID");
2 | var form = FormApp.openById("NEW_GOOGLE_FORM_ID");
3 |
4 | function Install1stTrigger(){
5 | ScriptApp.newTrigger("updateStudents")
6 | .forSpreadsheet(ss)
7 | .onEdit()
8 | .create();
9 | }
10 |
11 | function CreateForm() {
12 | var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK)
13 | var sheets = ss.getSheets()
14 | var teachers = getTeacherNames()
15 |
16 | form.addMultipleChoiceItem();
17 | // set choices from first item to name of Sheets Tabs
18 | try {
19 | // Chance name of PAGE_BREAKS to match Tab Names
20 | for (i in ss.getSheets()){
21 | try {
22 | var pageBreak = pageBreaks[i].setTitle(teachers[i]);
23 | pageBreak.asPageBreakItem().setGoToPage(FormApp.PageNavigationType.SUBMIT)
24 | }
25 | // If there is an error, try and add a new PAGE_BREAK with the appropriate name
26 | catch(err){
27 | Logger.log(err)
28 | pageBreak = form.addPageBreakItem().setTitle(teachers[i])
29 | pageBreak.setGoToPage(FormApp.PageNavigationType.SUBMIT)
30 | Logger.log("Added PAGE_BREAK named %s",teachers[i])
31 | }
32 | Logger.log(pageBreak)
33 | // Add the items on the page - Lunch Count and Milk Count"
34 | /*form.addTextItem().setTitle("Lunch Count")*/
35 | // Pull the number of students, add them to bottom of the page
36 | var studentNames = getStudentNames(sheets[i])
37 | Logger.log("%s students in %s's class",j,teachers[i])
38 | form.addCheckboxItem().setTitle("Milk Count").setChoiceValues(studentNames)
39 | //Change Navigation to Submit
40 | form.addTextItem().setTitle("Number of Chocolate Milk")
41 | };
42 | }
43 | catch(err){
44 | Logger.log(err)
45 | };
46 | var firstItem = form.getItems()[0]
47 | firstItem.asMultipleChoiceItem()
48 | .setChoiceValues(teachers)
49 | // set navigation for each answer
50 | // have to do this manually :(
51 | }
52 |
53 | function updateStudents() {
54 | var classLists = form.getItems(FormApp.ItemType.CHECKBOX)
55 | for (i in classLists){
56 | var sheet = ss.getSheets()[i]
57 | var studentNames = getStudentNames(sheet)
58 | Logger.log(studentNames)
59 | classLists[i].asCheckboxItem().setChoiceValues(studentNames)
60 | }
61 | }
62 |
63 | function updateStaff(){
64 | var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK)
65 | var teacherNames = getTeacherNames()
66 | for (i in pageBreaks){
67 | pageBreaks[i].setTitle(teacherNames[i])
68 | }
69 | }
70 |
71 | function getTeacherNames(){
72 | var sheets = ss.getSheets()
73 | var teacher = new Array
74 | for (i in sheets){
75 | teacher[i] = sheets[i].getName()
76 | }
77 | return teacher
78 | }
79 |
80 | function getStudentNames(sheet){
81 | try{
82 | var studentNames = sheet.getRange("A1:A").getValues()
83 | for (j in studentNames){
84 | // Logger.log(studentNames[k].valueOf())
85 | if (studentNames[j].valueOf() != ''){
86 | Logger.log(studentNames[j])
87 | }
88 | }
89 | }catch(err){
90 | Logger.log("%s (%s)",i, err)
91 | i++
92 |
93 | }
94 | return studentNames
95 | }
96 |
--------------------------------------------------------------------------------
/Delta-OU/Delta OU.gs:
--------------------------------------------------------------------------------
1 | /* The object of this project is to easily assign the ability to move an OU containing Users or Computers or both from one parent OU to another. The idea being that the "targetOU" acts as a container, having all settings inherrited. When the Target is placed into a "newParentOU", it receives all the settings of it's new Parent.
2 |
3 | Authorized Session Users (Session.getActiveUser()) are stored in a Spreadsheet, along with the scope which they are allowed to change to/from (separate columns, 3 total)
4 |
5 | An Audit of executions is stored in the same Spreadsheet under the tab "DeltaOU Audit". The Audit includes Session User, TimeStamp targetOU, Original Parent OU, newParentOU, and Success/Fail/Retry status.
6 | */
7 | // West Grand's OU Structure
8 | /*****LABS**********Parent OUs*******TESTS*******
9 | * Distance Lab * K8/Students * NWEA Testing *
10 | * Trips Lounge * HS/Students * Pearson *
11 | * North Lab * MS/Students * STAR *
12 | * South Lab * ES/Students * *
13 | * Career Center * * *
14 | ************************************************/
15 |
16 | function MoveOU(target, newParent){
17 | Logger.log(target, newParent)
18 | var DeltaOU = GettingStarted(target,newParent)
19 |
20 | if (DeltaOU.State != "Fail"){ //test to see if User Authorized
21 | try{
22 | var resource = {
23 | parentOrgUnitPath : DeltaOU.NewParentOU[0].getOrgUnitPath()
24 | }
25 | var orgUnitPath = DeltaOU.TargetOU[0].orgUnitId
26 | var customerId = DeltaOU.CustomerId
27 | var changeTo = AdminDirectory.Orgunits.update(resource, customerId, [orgUnitPath]) //changes parentOrgUnitPath to NewParent
28 | DeltaOU.State = "Success"
29 | var aftermath = GettingStarted(target,newParent)
30 | Logger.log(aftermath.TargetOU[0].parentOrgUnitPath)
31 | }
32 | catch(err){
33 | Logger.log(DeltaOU.State)
34 | }
35 | }
36 | editAuditLog(DeltaOU) //write attempt to Audit Log
37 | }
38 |
39 | function GettingStarted(a,b) {
40 | var ss, userSheet, auditSheet //variables referring to Spreadsheet
41 | var searchTargetOU, searchNewParentOU,userScope //variables referring to Search Terms for OUs
42 | var allOUs, targetOU, parentOU, newParentOU //variables referring to OU Objects/Arrays
43 | var user, timeStamp, state, page, pageToken //Other variables
44 |
45 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
46 | var SSID = "SPREADSHEET_ID" //temporary hard coded
47 | var customerId = 'my_customer'
48 |
49 | ss = SpreadsheetApp.openById(SSID)
50 | userSheet = ss.getSheets()[0].setName("Authorized Users")
51 | auditSheet = ss.getSheetByName("DeltaOU Audit")
52 | if(auditSheet == null){
53 | auditSheet = ss.insertSheet().setName("DeltaOU Audit")
54 | }
55 |
56 | var scope = getUserScope(userSheet)
57 | if ((typeof scope) == "object"){ //test to see if User is Authorized.
58 |
59 | allOUs = new Array
60 | targetOU = new Array
61 | parentOU = new Array
62 | newParentOU = new Array
63 |
64 | searchTargetOU = new RegExp(a+"$")
65 | searchNewParentOU = new RegExp(b+"$")
66 | userScope = scope.scopeA
67 | user = Session.getActiveUser()
68 | timeStamp = new Date()
69 |
70 | //list OUs - push to OU arrays within userScope
71 | do{
72 | page = AdminDirectory.Orgunits.list(customerId,{
73 | domain: domain,
74 | type: 'all',
75 | maxResults: 100,
76 | pageToken: pageToken
77 | });
78 | for (i=0 ; i < page.organizationUnits.length; i++ ){
79 | if (userScope.test(page.organizationUnits[i].parentOrgUnitPath)){
80 | allOUs.push(page.organizationUnits[i])
81 |
82 | if (searchNewParentOU.test(page.organizationUnits[i].orgUnitPath)){
83 | newParentOU.push(page.organizationUnits[i])};
84 | if (searchTargetOU.test(page.organizationUnits[i].orgUnitPath)){
85 | targetOU.push(page.organizationUnits[i]);
86 | parentOU.push(AdminDirectory.Orgunits.get(customerId, [page.organizationUnits[i].parentOrgUnitId]))};
87 | }
88 | }
89 | pageToken = page.nextPageToken;
90 | }
91 | while(pageToken) //end push to OU arrays
92 |
93 | state = ""
94 | //store values in JSON object
95 | var DeltaOU = { Spreadsheet: ss,
96 | UserSheet: userSheet,
97 | AuditSheet: auditSheet,
98 | AllOUs: allOUs,
99 | TargetOU: targetOU,
100 | ParentOU: parentOU,
101 | NewParentOU: newParentOU,
102 | User: user,
103 | TimeStamp: timeStamp,
104 | State: state,
105 | CustomerId: customerId}
106 | Logger.log(DeltaOU.NewParentOU)
107 | if (DeltaOU.NewParentOU[0].orgUnitId == DeltaOU.ParentOU[0].orgUnitId){
108 | DeltaOU.State = "Fail"
109 | Logger.log("Already Moved")
110 | }
111 | }
112 | else { //if user is not Authorized
113 | DeltaOU = {User: Session.getActiveUser(),
114 | AuditSheet: auditSheet,
115 | TimeStamp: new Date(),
116 | TargetOU: [{orgUnitPath:"Unauthorized User"}],
117 | ParentOU: [{orgUnitPath:"Unauthorized User"}],
118 | NewParentOU: [{orgUnitPath:"Unauthorized User"}],
119 | State: "Fail"}
120 | }
121 | return DeltaOU
122 | }
123 |
124 | function getUserScope(userSheet){
125 | var sessionUser = Session.getActiveUser()
126 | var userRange = userSheet.getRange("A2:C").getValues()
127 | var scope
128 | for (i in userRange){
129 | var user = userRange[i][0] //Column A
130 | var scopeA = userRange[i][1] //Column B
131 | var scopeB = userRange[i][2] //Column C
132 | if (user == sessionUser){
133 | scope = {user: new RegExp(user),
134 | scopeA: new RegExp(scopeA),
135 | scopeB: new RegExp(scopeB)}
136 | Logger.log(scope)
137 | return scope
138 | }
139 | else{
140 | scope = "User Not Authorized";
141 | continue
142 | }
143 | return scope
144 | }
145 | }
146 | function deviceOUs(){
147 | AdminDirectory.Chromeosdevices.list(customerId, optionalArgs).chromeosdevices[1]
148 | }
149 | function editAuditLog(DeltaOU){
150 | try{
151 | var sheet = DeltaOU.AuditSheet
152 | var user = DeltaOU.User
153 | var timeStamp = DeltaOU.TimeStamp
154 | var targetOU = DeltaOU.TargetOU[0].orgUnitPath
155 | var originalOU = DeltaOU.ParentOU[0].orgUnitPath
156 | var newOU = DeltaOU.NewParentOU[0].orgUnitPath
157 | var state = DeltaOU.State}
158 | catch(err){
159 | Logger.log(err.message)
160 | }
161 | if (state == undefined){state = "Fail"}
162 | sheet.appendRow([user,timeStamp,targetOU,originalOU,newOU,state])
163 | }
164 |
--------------------------------------------------------------------------------
/Delta-OU/README.md:
--------------------------------------------------------------------------------
1 | The object of this project is to easily assign the ability to move an OU containing Users or Computers or both from one parent OU to another. The idea being that the "targetOU" acts as a container, having all settings inherrited. When the Target is placed into a "newParentOU", it receives all the settings of it's new Parent.
2 |
3 | Authorized Session Users (Session.getActiveUser()) are stored in a Spreadsheet, along with the scope which they are allowed to change to/from (separate columns, 3 total)
4 |
5 | An Audit of executions is stored in the same Spreadsheet under the tab "DeltaOU Audit". The Audit includes Session User, TimeStamp targetOU, Original Parent OU, newParentOU, and Success/Fail/Retry status.
6 |
--------------------------------------------------------------------------------
/Delta-OU/gui.gs:
--------------------------------------------------------------------------------
1 | var DOMAIN = Session.getEffectiveUser().getEmail().split("@")[1]
2 | var ss = "YOUR_SPREADSHEET_ID"
3 |
4 | function doGet() {
5 | return HtmlService.createHtmlOutputFromFile('Index')
6 | .setSandboxMode(HtmlService.SandboxMode.IFRAME);
7 | }
8 |
9 | function doSomething() {
10 | var htmlOption = new Array
11 | var userSheet = ss.getSheets()[0]
12 | var scope = getUserScope(userSheet)
13 | var userScope = new RegExp(scope.scopeA)
14 | var parentScope = new RegExp(scope.scopeB)
15 | var customerId = 'my_customer';
16 | var domain = DOMAIN; // temporary hard coded
17 | var pageToken, page
18 | var scopeA = new Array;
19 | var scopeB = new Array;
20 |
21 | //getAll OUs
22 | do{
23 | page = AdminDirectory.Orgunits.list(customerId,{
24 | domain: domain,
25 | type: 'all',
26 | maxResults: 100,
27 | pageToken: pageToken
28 | });
29 | for (i=0 ; i < page.organizationUnits.length; i++ ){
30 | if (userScope.test(page.organizationUnits[i].parentOrgUnitPath)){
31 | scopeA.push(page.organizationUnits[i])
32 | }
33 | if (parentScope.test(page.organizationUnits[i].parentOrgUnitPath)){
34 | scopeB.push(page.organizationUnits[i])
35 | }
36 | }
37 | pageToken = page.nextPageToken;
38 | }
39 | while(pageToken);
40 | for (i in scopeB){
41 | htmlOption[i] = {parentValue: '',
42 | parentName: '',
43 | targetValue: scopeB[i].orgUnitPath,
44 | targetName: scopeB[i].orgUnitPath}
45 | }
46 | for (i in scopeA){
47 | htmlOption[i].parentValue = scopeA[i].orgUnitPath,
48 | htmlOption[i].parentName = scopeA[i].name
49 | }
50 | return htmlOption;
51 | }
52 |
--------------------------------------------------------------------------------
/Delta-OU/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Target Lab
15 |
16 |
17 |
18 | Move To
25 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
57 |
--------------------------------------------------------------------------------
/ES-Student-Update/README.md:
--------------------------------------------------------------------------------
1 | Associated with a Google Sheet.
2 |
3 | Goes through all OUs matching a RegExp and resets their Password to match a given Schema. Then records the user's information within a Google Sheet. Then arranges the users into 3 columns and exports the Sheet in a PDF format.
4 | Much of this is dependant on OU Structure resembling West Grand School District's
5 |
6 | Requires AdminSDK to be enabled.
7 |
--------------------------------------------------------------------------------
/ES-Student-Update/UpdateStudents.gs:
--------------------------------------------------------------------------------
1 | function updateStudents() {
2 | var DOMAIN = Session.getEffectiveUser().getEmail().split("@")[1]
3 | var OU = '1.0 ES Student' //String value of OU you want to update
4 | var ss = SpreadsheetApp.openById("SPREADSHEET_ID")
5 | var sheet = ss.getSheetByName(OU.replace(" Student","")) //OCD Cleanup... My sheet was named '1.0 ES'
6 | var userList = []
7 | listAllStudents(OU)
8 |
9 | for (i in userList){
10 | var user = userList[i];
11 | var userName = user.getName().getFullName()
12 | var userGrade = user.getOrgUnitPath().slice(user.orgUnitPath.lastIndexOf(OU),user.orgUnitPath.lastIndexOf("/Class")) //BASED ON MY OU STRUCTURE
13 | userGrade = userGrade.slice(userGrade.lastIndexOf("/")+1) // BASED ON MY OU STRUCTURE
14 | var userPassword = "WGSD_" //SCHEMA of new Password
15 | userPassword += user.orgUnitPath.slice(user.orgUnitPath.lastIndexOf("Class")+9) //SCHEMA for Password
16 | var username = user.primaryEmail
17 | //update student password to match userPassword
18 | var changeTo = {password: userPassword,
19 | suspended: false,
20 | changePasswordAtNextLogin:false}
21 |
22 | changeTo = AdminDirectory.Users.update(changeTo,user.primaryEmail)
23 | // sheet.appendRow(["Name: ",userName])
24 | sheet.appendRow(["Email: ",username])
25 | sheet.appendRow(["Grade: ",userGrade])
26 | sheet.appendRow(["Password: ",userPassword])
27 | sheet.appendRow([" "])
28 | }
29 |
30 | //put list into 4 columns
31 | var lastRow = sheet.getLastRow()
32 | var row = parseInt((sheet.getLastRow())/4)
33 | var column = 1 //sheet.getLastColumn()
34 | var cell = sheet.getRange((row),column)
35 |
36 | var cellValue = cell.getValue()
37 | do{
38 | row++;
39 | cell = sheet.getRange(row,column)
40 | cellValue = cell.getValue()
41 | }while(cellValue != " ")
42 |
43 | var numRows = row
44 | //second set
45 | for (i = 1; i < 5; i++){
46 | row = numRows*i
47 | var range = sheet.getRange(row+1, column, numRows, 2)
48 | var copyToColumn = (3*i+1)
49 | var copyTo = sheet.getRange(1, copyToColumn, numRows, 2)
50 | range.moveTo(copyTo)
51 | }
52 | //reformat cells spacing
53 |
54 | var i = 1
55 | do{
56 | Logger.log(i)
57 | sheet.autoResizeColumn(3*i-2)
58 | Logger.log("Column %s autoresized",3*i-2)
59 | sheet.autoResizeColumn(3*i-1)
60 | // Logger.log("Column %s autoresized",3*i-1)
61 | sheet.setColumnWidth((3*i), 25)
62 | // Logger.log("Column %s set to 50",3*i)
63 | i++
64 | } while (i<4)
65 |
66 | //export as a PDF
67 | var ssId = ss.getId()
68 | var pdf = DriveApp.getFileById(ssId).getAs('application/pdf').setName("Copy of Students.pdf")
69 | var newFile = DriveApp.createFile(pdf).getUrl()
70 | Logger.log("You can access your file at %s",newFile)
71 |
72 | /*****Referenced in Line 6 to populate userList*****/
73 | function listAllStudents(OU) {
74 | var re = new RegExp(OU)
75 | var pageToken, page, now
76 | now = new Date();
77 | do {
78 | page = AdminDirectory.Users.list({
79 | domain: DOMAIN,
80 | orderBy: 'familyName',
81 | maxResults: 100,
82 | pageToken: pageToken
83 | });
84 | var users = page.users;
85 | if (users) {
86 | for (var i = 0; i < users.length; i++) {
87 | var user = users[i];
88 | if (re.test(user.orgUnitPath)){
89 | userList.push(user)
90 | }
91 | }
92 | } else {
93 | Logger.log('No users found.');
94 | }
95 | pageToken = page.nextPageToken;
96 | } while (pageToken);
97 | }
98 | /*****End listAllStudents()*****/
99 | }
100 |
--------------------------------------------------------------------------------
/Groups-and-Group-Members/Clear Descriptions.gs:
--------------------------------------------------------------------------------
1 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
2 |
3 | //start functions
4 | function getClearGroupDescriptions(){
5 | var pageToken, page;
6 |
7 | do{
8 | page = AdminDirectory.Groups.list({
9 | domain: domain,
10 | maxResults: 100,
11 | pageToken: pageToken
12 | });
13 | var groups = page.groups;
14 | if (groups) {
15 | for (var i = 0; i < groups.length; i++) {
16 | var group = groups[i]
17 | var re = new RegExp("Classroom")
18 | if (!re.test(group)){
19 | Logger.log(group.name)
20 | try{
21 | var newDescription = {description: ''}
22 | group.description = newDescription
23 | Logger.log(group.description)
24 | }
25 | catch(err){
26 | Logger.log(err)}
27 | }}
28 | }
29 | else{
30 | Logger.log('No Groups Found')
31 | }} while (pageToken)
32 | }
33 |
--------------------------------------------------------------------------------
/Groups-and-Group-Members/Groups and Members.gs:
--------------------------------------------------------------------------------
1 | //variables to pass from UI
2 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
3 | var ss = SpreadsheetApp.openById('SPREADSHEET_ID');
4 |
5 | //start functions
6 | function getAllGroupUsers(){
7 | var pageToken, page;
8 | var sheet = ss.getSheets()[0]
9 |
10 | sheet.clear()
11 | do{
12 | page = AdminDirectory.Groups.list({
13 | domain: domain,
14 | maxResults: 100,
15 | pageToken: pageToken
16 | });
17 | var groups = page.groups;
18 | if (groups) {
19 | for (var i = 0; i < groups.length; i++) {
20 | var group = groups[i]
21 | /* try{ //comment out this section if you want to include all groups
22 | var re = new RegExp("[0-9]") //and here
23 | if(re.test(group.name)) { //and here
24 | Logger.log("Skipping %s - Student Group",group.name) //and here
25 | } //and here
26 | else{ //and here*/
27 | try{
28 | var col = sheet.getLastColumn()+1
29 | sheet.getRange(1, col).setValue(group.name+" ("+group.email+")")
30 | var groupUsers = AdminDirectory.Members.list(group.email).members
31 | for (var j = 0 ; j < groupUsers.length ; j++ ){
32 | var user = groupUsers[j].getEmail()
33 | sheet.getRange(j+2, col).setValue(user);
34 | }}
35 | catch(err){
36 | Utilities.sleep(1000)
37 | Logger.log(err.message)
38 | }
39 | /* }}
40 | catch(err){ //and here
41 | Logger.log(err)} //and here*/
42 | }
43 | //formatting sheet (Bold top row, resize columns
44 | sheet.getRange("A1:1").setFontWeight("900")
45 | var columns = sheet.getLastColumn();
46 | for (var n = 1; n < columns ; n++){
47 | sheet.autoResizeColumn(n)
48 | }
49 | }
50 | else{
51 | Logger.log('No Groups Found')
52 | }} while (pageToken)
53 | }
54 | function installOnSheet(){
55 | ScriptApp.newTrigger("getAllGroupUsers")
56 | .forSpreadsheet(ss)
57 | .onOpen()
58 | .create();}
59 |
--------------------------------------------------------------------------------
/Groups-and-Group-Members/README.md:
--------------------------------------------------------------------------------
1 | Clear Descriptions:
2 | I was asked in a forumn if there was a fast way to remove all the descriptions from all groups. This was the result.
3 | Requires AdminSDK to be enabled.
4 |
5 | Remove Empty Contact Groups
6 | Again, someone asked if there was a way to clear all of their empty groups from their Contacts. No AdminSDK, but does require the ContactsApp to be enabled.
7 |
8 | Groups and Group Members:
9 | Must be associated with a Google Sheet (eventually could make this an addon for Sheets).
10 | Clears all the data from the first Sheet of a Spreadsheet and imports the Groups and their Members in coumns. Could quite possibly be changed into a Group Inventory Addon for Sheets, akin to Chromebook Inventory, with the ability to update Groups, though this is currently not a feature in this script (but is a function within "Group OU Sync", another project).
11 |
12 | Lines 21 and 39 include code which is commented out that would exclude groups from the inventory, such as Student, Staff, or other Groups that fit in a Regular Expression.
13 |
14 | Requires AdminSDK to be enabled.
15 |
--------------------------------------------------------------------------------
/Groups-and-Group-Members/Remove Empty Contact Groups.gs:
--------------------------------------------------------------------------------
1 | function getContactGroups(){
2 | var groups = ContactsApp.getContactGroups()
3 | for (i in groups){
4 | var group = groups[i]
5 | var numGroupContacts = group.getContacts().length
6 | if (numGroupContacts == 0){
7 | Logger.log(group.getName())
8 | try{group.deleteGroup()
9 | }
10 | catch(err){}
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/HashSpreadsheet/README.md:
--------------------------------------------------------------------------------
1 | Proof of concept. Quickly search through a Google Sheet for a given value.
2 | Bruteforce (check every row until you get the correct one) method takes approx. 3 seconds for a 1000 row Sheet.
3 | This method takes approx. .3 seconds for the same sheet.
4 |
5 | Values in the sheet must be unique for this method to work. The Spreadsheet referenced is Public and contains numbers 1 - 1000 in col A and 1000 unique random numbers in col B.
6 |
7 | *TODO:* would like to be able to return multiple rows, or handle non-unique values.
8 |
--------------------------------------------------------------------------------
/HashSpreadsheet/hash.gs:
--------------------------------------------------------------------------------
1 | function test() {
2 | var ss = SpreadsheetApp.openById("1r8-pjJGmiNwXGsIftg3zkEuKmMKBuG9Ldc_MZpFyEYo");
3 | var sheet = ss.getSheets()[0];
4 | var lastRow = sheet.getLastRow();
5 |
6 | var x = getRandomInt(1,lastRow)
7 | var y = 2; //1 for 1ntegers, 2 for random values
8 | x = sheet.getRange(x,y).getValue()
9 | Logger.log("Searching for %s",x);
10 | var hashedValue = hash(sheet,lastRow,x,y);
11 | Logger.log("hashedValue = %s",hashedValue);
12 |
13 | function getRandomInt(min, max) {
14 | return Math.floor(Math.random() * (max - min)) + min;
15 | }
16 | }
17 | function hash(sheet,n,x,y){
18 | //searching for x in column y
19 | var min = 1, mid = (1+(n-1)/2);
20 | var max = n, that, i=0;
21 | x = ","+x.toString()+",";
22 | var re = new RegExp(x,"i");
23 | var gap = max-min;
24 |
25 | while ((that != x) && (min >= 0) && (max <= n) && (gap >= 4) && (i <= n)){
26 | var gap = Math.floor(max)-Math.floor(min);
27 | var floor = sheet.getRange(min, y, Math.ceil(gap/2)).getValues();
28 | var ceiling = sheet.getRange(mid, y, Math.ceil(gap/2)).getValues();
29 | switch(true){
30 | case re.test(floor.toString()):
31 | max = mid;
32 | that = floor.toString();
33 | break;
34 | case re.test(ceiling.toString()):
35 | min = mid;
36 | that = ceiling.toString();
37 | break;
38 | default:
39 | that = x
40 | break;
41 | }
42 | mid = Math.floor(min+(max-min)/2);
43 | i++
44 | }
45 | for (var j = min; j < max; j++){
46 | if(sheet.getRange(j, y).getValue() == x.substring(1,x.length-1)){
47 | that = sheet.getRange(j,y).getValue();
48 | return that;
49 | }
50 | }
51 | return that;
52 | }
53 |
--------------------------------------------------------------------------------
/List-Students-and-Other-Goodies/README.md:
--------------------------------------------------------------------------------
1 | Derivations of Google's Example to List all Users, documented on their developers.google.com tutortial site (https://developers.google.com/apps-script/advanced/admin-sdk-directory). All of these require AdminSDK enabled in order to function properly
2 |
3 | Added sheet and query. This would (without alteration) need to be added to a Spreadsheet as a bound script.
4 |
--------------------------------------------------------------------------------
/List-Students-and-Other-Goodies/listAllUsers.gs:
--------------------------------------------------------------------------------
1 | function listAllStudents() {
2 | //var re = new RegExp("Student"), allUsers = new Array(),
3 | var query = 'orgUnitPath = "Student"'
4 | var sheet = SpreadsheetApp.getActive().getActiveSheet()
5 |
6 | var pageToken, page, now
7 | now = new Date();
8 | do {
9 | page = AdminDirectory.Users.list({
10 | domain: Session.getEffectiveUser().getEmail().split("@")[1],
11 | orderBy: 'familyName',
12 | query: query,
13 | maxResults: 100,
14 | pageToken: pageToken
15 | });
16 | var users = page.users;
17 | if (users) {
18 | for (var i = 0; i < users.length; i++) {
19 | var user = users[i];
20 | sheet.appendRow([user]);
21 |
22 | // if (re.test(user.orgUnitPath)){
23 | // allUsers.push(user)
24 | // }
25 |
26 | }
27 | } else {
28 | Logger.log('No users found.');
29 | }
30 | pageToken = page.nextPageToken;
31 | } while (pageToken);
32 | // return allUsers
33 | }
34 |
--------------------------------------------------------------------------------
/List-Students-and-Other-Goodies/listInactiveStudents.gs:
--------------------------------------------------------------------------------
1 | function listAllStudents() {
2 | var re = new RegExp("Student"), inactiveUsers = new Array()
3 |
4 | var pageToken, page, now
5 | now = new Date();
6 | do {
7 | page = AdminDirectory.Users.list({
8 | domain: Session.getEffectiveUser().getEmail().split("@")[1],
9 | orderBy: 'familyName',
10 | maxResults: 100,
11 | pageToken: pageToken
12 | });
13 | var users = page.users;
14 | if (users) {
15 | for (var i = 0; i < users.length; i++) {
16 | var user = users[i];
17 | //you can add parameters to check OUs
18 | if (re.test(user.orgUnitPath)){
19 | if (Date.parse(now) - Date.parse(user.creationTime) < (1000*60*60*24*30)) {
20 | Logger.log('%s (%s). - %s', user.primaryEmail, user.creationTime, user.lastLoginTime);
21 | inactiveUsers.push(user)
22 | }
23 | }
24 | }
25 | } else {
26 | Logger.log('No users found.');
27 | }
28 | pageToken = page.nextPageToken;
29 | } while (pageToken);
30 | return inactiveUsers
31 | }
32 |
--------------------------------------------------------------------------------
/OU-2-Group/OUs2Group.gs:
--------------------------------------------------------------------------------
1 | function OUs2Groups() {
2 | var OUs = [], Groups = {group:[],groupMembers:[]};
3 | var DOMAIN = Session.getEffectiveUser().getEmail().split("@")[1], customerId = 'my_customer', page, pageToken
4 | var query = "orgUnitPath='/Student'"
5 |
6 | do{
7 | page = AdminDirectory.Users.list({
8 | domain:DOMAIN,
9 | query: query,
10 | type: 'all',
11 | maxResults: 100,
12 | pageToken: pageToken
13 | });
14 | for (i in page.users){
15 | var user = page.users[i].primaryEmail;
16 | var userOrg = page.users[i].orgUnitPath;
17 | var regexp = new RegExp(userOrg);
18 | Groups.group[i] = userOrg.replace(/\/.*\//,'');
19 | Groups.groupMembers[i] = user;
20 | if (regexp.test(OUs)){
21 | continue;}
22 | else{
23 | OUs.push(userOrg);
24 | };
25 | };
26 | pageToken = page.nextPageToken
27 | }
28 | while(pageToken);
29 | var allGroups, currentGroups = [];
30 | do{
31 | allGroups = AdminDirectory.Groups.list({
32 | domain:DOMAIN,
33 | maxResults:200,
34 | pageToken:pageToken
35 | });
36 | for (i in allGroups.groups){
37 | currentGroups.push(allGroups.groups[i].name)
38 | }
39 | pageToken = allGroups.nextPageToken
40 | }while(pageToken);
41 |
42 | for (i in OUs){ //OCD Extract OU Name.
43 | OUs[i] = OUs[i].replace(/\/.*\//,'')
44 |
45 | regexp = new RegExp(OUs[i])
46 | if (regexp.test(currentGroups)){
47 | continue;
48 | }
49 | else{
50 | var email = (OUs[i]+"@"+DOMAIN).replace(' ','',"g")
51 | var resource = {email:email,
52 | name:OUs[i]}
53 | AdminDirectory.Groups.insert(resource)
54 | currentGroups.push(resource.name)
55 | }
56 | }
57 | try{
58 | for (i in Groups.groupMembers){
59 | resource = {email:Groups.groupMembers[i],
60 | role: "MEMBER"}
61 | var groupKey = (Groups.group[i]+"@"+DOMAIN).replace(' ','',"g")
62 | Logger.log("Adding %s to group %s",resource.email, groupKey)
63 | // AdminDirectory.Members.insert(resource, groupKey)
64 | }
65 | }
66 | catch(err){Logger.log(err)}
67 | }
68 |
--------------------------------------------------------------------------------
/OU-2-Group/README.md:
--------------------------------------------------------------------------------
1 | Requires AdminSDK
2 |
3 | Create Groups based on User OU and populate those groups with appropriate members.
4 |
5 | TODO:
6 | Set created Group Permissions to something other than Default.
7 | Cleanup old/other group memberships - If a member is moved, remove them from the old group.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # random-GAS-scripts
2 | Some of my random files that I created during my tenure at West Grand School District to help me manage my GAFE Domain easier
3 |
--------------------------------------------------------------------------------
/RandomPassword-for-Substitute-Teacher-Accounts/Change Password.gs:
--------------------------------------------------------------------------------
1 | /* The Sub accounts listed in "getSubs()" have their passwords reset
2 | The Manager accounts have the reset password emailed to them.
3 | The variables are given objects referencing each respective value (sub, manager)
4 | Sub accounts get different passwords since the ChangePassword() function is called for each organization.
5 | */
6 | function getSubs(){
7 | var hs = {sub:"hs.sub@wgsd.us", //HS Sub Account
8 | manager:"clarkk@wgsd.us"} //HS Secretary
9 | var ms = {sub:"ms.sub@wgsd.us",
10 | manager:"henderhanc@wgsd.us"}
11 | var es = {sub:"es.sub@wgsd.us",
12 | manager:"porlask@wgsd.us"}
13 | ChangePassword(hs.sub, hs.manager)
14 | ChangePassword(ms.sub, ms.manager)
15 | ChangePassword(es.sub, es.manager)
16 | }
17 | function ChangePassword(sub, manager) {
18 | function getRandomInt(min, max) {
19 | return Math.floor(Math.random() * (max - min)) + min;
20 | }
21 | //define random password will generate an 8 digit random password [a-z],[0-9]
22 | var changeTo = {password:getRandomInt(78364164095,2821109907456).toString(36)}
23 | //today's date
24 | var now = new Date()
25 | now = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getYear()
26 | //mail variables
27 | var _subject = "New password for " + sub + " for the week of " + now
28 | var _body = "The password for " + sub + " has been changed. The password for the week of " + now + " is " + changeTo.password
29 | //take action, change the password
30 |
31 | changeTo = AdminDirectory.Users.update(changeTo, sub)
32 |
33 | //send email to manager(s)
34 | Logger.log(_body);
35 | MailApp.sendEmail(manager, _subject, _body)
36 | }
37 |
--------------------------------------------------------------------------------
/RandomPassword-for-Substitute-Teacher-Accounts/README.md:
--------------------------------------------------------------------------------
1 | This script is set to run on a schedule, once a week. An email is generated for each of the email accounts and sent to the respective manager.
2 |
3 | This could have been more elegant, creating 2 arrays (one for managers, one for subs) and looping through a for statement rather than 3 objects calling the function manually 3 times, but either way works. If I were making this as an addon, I believe I would use the 2 array method.
4 |
5 | Requires AdminSDK to be enabled.
6 |
--------------------------------------------------------------------------------
/Remove-Aliases/README.md:
--------------------------------------------------------------------------------
1 | Robert Petitto requested -
2 |
3 | Aside from using BetterCloud or GAMs, is there any way to easily update our students in bulk. Specifically, I'd like to remove their Alias which shows up in the directory.
4 |
5 | This is my solution -
6 | OK - Here's the Script to do just what +Robert Petitto asked - Remove all aliases from a limited group (Based on OUs).
7 | You will need to enable the AdminSDK in the Dev Console and the Advanced Preferences (both in the same dropdown).
8 |
--------------------------------------------------------------------------------
/Remove-Aliases/Remove Aliases.gs:
--------------------------------------------------------------------------------
1 | var DOMAIN = Session.getEffectiveUser().getEmail().split("@")[1]
2 |
3 | function getOUs(match){
4 | match = new RegExp("Students")
5 | var pageToken, users = new Array()
6 | do{
7 | var allUsers = AdminDirectory.Users.list({
8 | domain: DOMAIN,
9 | maxResults: 100,
10 | orderBy: 'familyName',
11 | pageToken: pageToken})
12 |
13 | for (var i in allUsers.users){
14 | if (match.test(allUsers.users[i].orgUnitPath)){
15 | users.push(allUsers.users[i])
16 | }
17 | }
18 | pageToken = allUsers.pageToken
19 | }while(pageToken){}
20 | // Do Stuff with Users
21 | for (var i in users){
22 | var user = users[i].primaryEmail
23 | //get all of users aliaes
24 | var aliases = AdminDirectory.Users.Aliases.list(user).aliases
25 | for (var j in aliases){
26 | var alias = aliases[j].alias
27 | //remove aliases
28 | AdminDirectory.Users.Aliases.remove(user, alias)
29 | Logger.log("Removed Alias %s from %s", alias, user)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Remove-sites/README.md:
--------------------------------------------------------------------------------
1 | ###Setup
2 | ####Enable the AdminSDK library.
3 | ~~Change "YOURDOMAIN" to the name of the Domain which you manage.~~
4 |
5 | This script removes all pages from a site and transfers ownership of that site to the user executing the script.
6 |
7 | Google Apps Script no longer contains an API call to delete a site - this must be done manually through the GUI.
8 |
9 | ###RemoveUser.gs
10 | A script which will remove a user's role from all sites that don't match the Exceptions.
11 | Change the values for ~~domain~~, user, and exception to match your criteria.
12 |
13 | Set the value of the variables removeViewer, removeOwner, and removeEditor to true for the roles you want to remove from the target user.
14 |
15 | Could have also been done using a for/case loop in place of the multiple if statements.
16 |
--------------------------------------------------------------------------------
/Remove-sites/RemoveUser.gs:
--------------------------------------------------------------------------------
1 | function removeUser() {
2 | var allSites, site, domain = Session.getEffectiveUser().getEmail().split("@")[1], viewers, editors, owners, user = new RegExp("SomeUser")
3 | var removeEditor = false
4 | var removeOwner = false
5 | var removeViewer = false
6 | var exceptions = new RegExp("SomeWebsiteName")
7 |
8 | allSites = SitesApp.getAllSites(domain)
9 | for (i in allSites){
10 | site = allSites[i];
11 | viewers = site.getViewers()
12 | editors = site.getEditors()
13 | owners = site.getOwners()
14 |
15 | if (exceptions.test(site.getName())){
16 | Logger.log("Skipping Site %s",site.getUrl())
17 | continue;}
18 | if (removeViewer){
19 | if (user.test(viewers)){
20 | for (j in viewers){
21 | if (user.test(viewers[j])){
22 | site.removeViewer(viewers[j])
23 | }}
24 | Logger.log("Viewer - %s (%s)",site.getName(), site.getUrl())
25 | }}
26 | if (removeEditor){
27 | if (user.test(editors)){
28 | for (j in editors){
29 | if (user.test(editors[j])){
30 | site.removeViewer(editors[j])
31 | }}
32 | Logger.log("Editor - %s (%s)",site.getName(), site.getUrl())
33 | }}
34 | if (removeOwner){
35 | if (user.test(owners)){
36 | for (j in owners){
37 | if (user.test(owners[j])){
38 | site.removeViewer(owners[j])
39 | }}
40 | Logger.log("Owner - %s (%s)",site.getName(), site.getUrl())
41 | }}
42 | }
43 | }
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Remove-sites/SuspendedUsers.gs:
--------------------------------------------------------------------------------
1 | function removeSites() {
2 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
3 | var allSites = SitesApp.getAllSites(domain)
4 |
5 | for (i in allSites){
6 | var page
7 | var owners = allSites[i].getOwners()
8 | var site = allSites[i]
9 | try{ // if User is suspended
10 | if (AdminDirectory.Users.get(owners[0].getEmail()).suspended) {
11 | page = site.getAllDescendants()
12 | for (i in page){
13 | Logger.log(page[i].getName() +" Deleted")
14 | //page[i].deletePage()
15 | }
16 | //Change site ownership
17 | site.removeOwner(owner)
18 | Logger.log("Removed %s as Owner", owners)
19 | site.addOwner(Session.getActiveUser())
20 | }
21 | }
22 | catch(err){ // if User is deleted
23 | page = site.getAllDescendants()
24 | for (i in page){
25 | Logger.log(page[i].getName() +" Deleted")
26 | page[i].deletePage()
27 | //Change site ownership
28 | site.removeOwner(owners)
29 | Logger.log("Removed %s as Owner", owners)
30 | // site.addOwner(Session.getActiveUser())
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/State-Abbreviation-converter/find-and-replace.gs:
--------------------------------------------------------------------------------
1 | function findandreplace() {
2 | var sheet = SpreadsheetApp.getActiveSheet();
3 | var row = 1, numRows = sheet.getMaxRows()
4 | var col = 1 // column index (A=1, B=2, C=3, etc.) of the row to find/replace
5 | var data = sheet.getRange(row, col, numRows).getValues()
6 | for (i in data) {
7 | row = i;
8 | switch(true){
9 | case (data[i][0] == "AL"):
10 | row++;
11 | sheet.getRange(row,col).setValue("Alabama");
12 | break;
13 | case (data[i][0] == "AZ"):
14 | row++;
15 | sheet.getRange(row,col).setValue("Arizona");
16 | break;
17 | case (data[i][0] == "CA"):
18 | row++;
19 | sheet.getRange(row,col).setValue("California");
20 | break;
21 | case (data[i][0] == "CO"):
22 | row++;
23 | sheet.getRange(row,col).setValue("Colorado");
24 | break;
25 | case (data[i][0] == "CT"):
26 | row++;
27 | sheet.getRange(row,col).setValue("Connecticut");
28 | break;
29 | case (data[i][0] == "DE"):
30 | row++;
31 | sheet.getRange(row,col).setValue("Delaware");
32 | break;
33 | case (data[i][0] == "FL"):
34 | row++;
35 | sheet.getRange(row,col).setValue("Florida");
36 | break;
37 | case (data[i][0] == "GA"):
38 | row++;
39 | sheet.getRange(row,col).setValue("Georgia");
40 | break;
41 | case (data[i][0] == "IA"):
42 | row++;
43 | sheet.getRange(row,col).setValue("Iowa");
44 | break;
45 | case (data[i][0] == "IL"):
46 | row++;
47 | sheet.getRange(row,col).setValue("Illinois");
48 | break;
49 | case (data[i][0] == "IN"):
50 | row++;
51 | sheet.getRange(row,col).setValue("INdiana");
52 | break;
53 | case (data[i][0] == "KS"):
54 | row++;
55 | sheet.getRange(row,col).setValue("Kansas");
56 | break;
57 | case (data[i][0] == "KY"):
58 | row++;
59 | sheet.getRange(row,col).setValue("Kentucky");
60 | break;
61 | case (data[i][0] == "LA"):
62 | row++;
63 | sheet.getRange(row,col).setValue("Louisiana");
64 | break;
65 | case (data[i][0] == "MA"):
66 | row++;
67 | sheet.getRange(row,col).setValue("Massachusetts");
68 | break;
69 | case (data[i][0] == "MD"):
70 | row++;
71 | sheet.getRange(row,col).setValue("Maryland");
72 | break;
73 | case (data[i][0] == "ME"):
74 | row++;
75 | sheet.getRange(row,col).setValue("Maine");
76 | break;
77 | case (data[i][0] == "MI"):
78 | row++;
79 | sheet.getRange(row,col).setValue("Michigan");
80 | break;
81 | case (data[i][0] == "MN"):
82 | row++;
83 | sheet.getRange(row,col).setValue("Minnesota");
84 | break;
85 | case (data[i][0] == "MO"):
86 | row++;
87 | sheet.getRange(row,col).setValue("Missouri");
88 | break;
89 | case (data[i][0] == "MS"):
90 | row++;
91 | sheet.getRange(row,col).setValue("Mississippi");
92 | break;
93 | case (data[i][0] == "MT"):
94 | row++;
95 | sheet.getRange(row,col).setValue("Montana");
96 | break;
97 | case (data[i][0] == "NC"):
98 | row++;
99 | sheet.getRange(row,col).setValue("North Carolina");
100 | break;
101 | case (data[i][0] == "ND"):
102 | row++;
103 | sheet.getRange(row,col).setValue("North Dakota");
104 | break;
105 | case (data[i][0] == "NE"):
106 | row++;
107 | sheet.getRange(row,col).setValue("Nebraska");
108 | break;
109 | case (data[i][0] == "NH"):
110 | row++;
111 | sheet.getRange(row,col).setValue("New Hampshire");
112 | break;
113 | case (data[i][0] == "NJ"):
114 | row++;
115 | sheet.getRange(row,col).setValue("New Jersey");
116 | break;
117 | case (data[i][0] == "NM"):
118 | row++;
119 | sheet.getRange(row,col).setValue("New Mexico");
120 | break;
121 | case (data[i][0] == "NV"):
122 | row++;
123 | sheet.getRange(row,col).setValue("Nevada");
124 | break;
125 | case (data[i][0] == "NY"):
126 | row++;
127 | sheet.getRange(row,col).setValue("New York");
128 | break;
129 | case (data[i][0] == "OH"):
130 | row++;
131 | sheet.getRange(row,col).setValue("Ohio");
132 | break;
133 | case (data[i][0] == "OK"):
134 | row++;
135 | sheet.getRange(row,col).setValue("Oklahoma");
136 | break;
137 | case (data[i][0] == "OR"):
138 | row++;
139 | sheet.getRange(row,col).setValue("Oregon");
140 | break;
141 | case (data[i][0] == "PA"):
142 | row++;
143 | sheet.getRange(row,col).setValue("Pennsylvania");
144 | break;
145 | case (data[i][0] == "RI"):
146 | row++;
147 | sheet.getRange(row,col).setValue("Rhode Island");
148 | break;
149 | case (data[i][0] == "SC"):
150 | row++;
151 | sheet.getRange(row,col).setValue("South Carolina");
152 | break;
153 | case (data[i][0] == "SD"):
154 | row++;
155 | sheet.getRange(row,col).setValue("South Dakota");
156 | break;
157 | case (data[i][0] == "TN"):
158 | row++;
159 | sheet.getRange(row,col).setValue("Tennessee");
160 | break;
161 | case (data[i][0] == "TX"):
162 | row++;
163 | sheet.getRange(row,col).setValue("Texas");
164 | break;
165 | case (data[i][0] == "UT"):
166 | row++;
167 | sheet.getRange(row,col).setValue("Utah");
168 | break;
169 | case (data[i][0] == "VA"):
170 | row++;
171 | sheet.getRange(row,col).setValue("Virginia");
172 | break;
173 | case (data[i][0] == "VT"):
174 | row++;
175 | sheet.getRange(row,col).setValue("Vermont");
176 | break;
177 | case (data[i][0] == "WA"):
178 | row++;
179 | sheet.getRange(row,col).setValue("Washington");
180 | break;
181 | case (data[i][0] == "WI"):
182 | row++;
183 | sheet.getRange(row,col).setValue("Wisconsin");
184 | break;
185 | case (data[i][0] == "WV"):
186 | row++;
187 | sheet.getRange(row,col).setValue("West Virginia");
188 | break;
189 | case (data[i][0] == "WY"):
190 | row++;
191 | sheet.getRange(row,col).setValue("Wyoming");
192 | break;
193 | };
194 | };
195 | };
196 |
--------------------------------------------------------------------------------
/Suspend-OU/README.md:
--------------------------------------------------------------------------------
1 | Quickly suspend all the users within an OU, or list of OUs
2 |
3 | Values within the Array 'a' become values of a regexp that will suspend all the users for all OUs which match the regexp.
4 |
5 | **Requires AdminSDK to be enabled.**
6 |
--------------------------------------------------------------------------------
/Suspend-OU/Suspend OU.gs:
--------------------------------------------------------------------------------
1 | function getUsers(OU) {
2 | var DOMAIN = Session.getEffectiveUser().getEmail().split("@")[1]
3 | OU = new RegExp(OU)
4 | var pages, pageToken, users = new Array(), user
5 |
6 | do{
7 | pages = AdminDirectory.Users.list({
8 | domain:DOMAIN,
9 | orderBy: "familyName",
10 | maxResults: 100,
11 | pageToken: pageToken})
12 | //Define which users to use
13 | for (var i in pages.users)
14 | if (OU.test(pages.users[i].orgUnitPath)){
15 | users.push(pages.users[i])}
16 | pageToken = pages.nextPageToken
17 | }
18 | while(pageToken){}
19 | //Do stuff with Users
20 | return users
21 | }
22 |
23 | function suspendOU(){
24 | var a = ["Outgoing Staff"], OUs // Comma Separated Strings of the Unique OU Names you wish to Suspend the users within
25 | for (OUs in a){
26 | var users = getUsers(a[OUs])
27 | for (var i in users){
28 | var userKey = users[i].primaryEmail
29 | var resource = {suspended : true}
30 | AdminDirectory.Users.update(resource, userKey)
31 | Logger.log("%s was suspended",userKey)
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sync-OU-to-Group/GetNewUsers.gs:
--------------------------------------------------------------------------------
1 | function getNewUsers(match){
2 | var newMembers = new Array()
3 | var groupRow = new Number(3), groupColumn = new Number(0)
4 | var sheet = SpreadsheetApp.openById("SPREADSHEET_ID").getSheets()[1]
5 | var range = sheet.getRange(1, 1, sheet.getMaxRows(),sheet.getMaxColumns()).getValues()
6 |
7 | //Get the Group Index column From Sheet (b)
8 | for (var i in range[0]){
9 | if (range[0][i] == match){
10 | var groupIndex = i
11 | for (var j in range){
12 | if (range[j][groupIndex] != ''){
13 | newMembers.push(range[j][groupIndex])
14 | }
15 | }
16 | }
17 | }
18 | return newMembers
19 | }
20 |
--------------------------------------------------------------------------------
/Sync-OU-to-Group/ImportGroups.gs:
--------------------------------------------------------------------------------
1 | function getAllGroupUsers(){
2 | var domain = 'YOURDOMAIN'
3 | var ss = SpreadsheetApp.openById("SPREADSHEET_ID")
4 |
5 | var pageToken, page;
6 | var sheet = ss.getSheets()[1]
7 |
8 | sheet.clear()
9 | do{
10 | page = AdminDirectory.Groups.list({
11 | domain: domain,
12 | maxResults: 100,
13 | pageToken: pageToken
14 | });
15 | var groups = page.groups;
16 | if (groups) {
17 | for (var i = 0; i < groups.length; i++) {
18 | var group = groups[i]
19 | try{
20 | var col = sheet.getLastColumn()+1
21 | sheet.getRange(1, col).setValue(group.name)
22 | var groupUsers = AdminDirectory.Members.list(group.email).members
23 | for (var j = 0 ; j < groupUsers.length ; j++ ){
24 | var user = groupUsers[j].getEmail()
25 | sheet.getRange(j+2, col).setValue(user);
26 | }
27 | sheet.autoResizeColumn(col)
28 | }
29 | catch(err){
30 | Utilities.sleep(1000)
31 | Logger.log(err.message)
32 | }
33 | }
34 | sheet.getRange("A1:1").setFontWeight("900")
35 | var columns = sheet.getLastColumn();
36 | for (var n = 1; n < columns ; n++){
37 | sheet.autoResizeColumn(n)
38 | }
39 | }
40 | else{
41 | Logger.log('No Groups Found')
42 | }
43 | pageToken = page.nextPageToken
44 | } while (pageToken){}
45 | }
46 |
--------------------------------------------------------------------------------
/Sync-OU-to-Group/ImportUsers.gs:
--------------------------------------------------------------------------------
1 | function importOUs() {
2 | var OUs, page, ss, sheet, pageToken, domain
3 | domain = "YOURDOMAIN"
4 | ss = SpreadsheetApp.openById("SPREADSHEET_ID")
5 | sheet = ss.getSheets()[0]
6 | sheet.clear()
7 | do{
8 | page = AdminDirectory.Orgunits.list("my_customer",{
9 | domain: domain,
10 | type: 'all',
11 | maxResults: 100,
12 | pageToken: pageToken
13 | });
14 | OUs = page.organizationUnits
15 |
16 | for (var i in OUs){
17 | OUs[i].orgId
18 | var column
19 | column = sheet.getLastColumn()+1
20 | sheet.getRange(1,column).setValue(OUs[i].name)
21 | sheet.getRange(2,column).setValue(OUs[i].orgUnitPath)
22 | sheet.getRange(3,column).setValue(OUs[i].orgUnitId)
23 | sheet.autoResizeColumn(column)
24 | }
25 | pageToken = page.nextPageToken;
26 | }while(pageToken){}
27 | }
28 |
29 | function WhereMyUsersAt(){
30 | var users, page, ss, sheet, pageToken, lastCol, domain
31 | domain = "YOURDOMAIN"
32 | ss = SpreadsheetApp.openById("SPREADSHEET_ID")
33 | sheet = ss.getSheets()[0]
34 | lastCol = sheet.getLastColumn()
35 |
36 | do{
37 | page = AdminDirectory.Users.list(
38 | {domain: domain,
39 | maxResults: 100,
40 | orderBy: "familyName",
41 | pageToken: pageToken
42 | })
43 | users = page.users
44 | for (var i in users){
45 | var column, lastRow, userOrg, j
46 | column = 1
47 | lastRow = 1
48 | userOrg = users[i].orgUnitPath
49 | for (column ; column < lastCol; column++){
50 | var orgPath = sheet.getRange(2, column).getValue()
51 | if (userOrg === orgPath){
52 | do{lastRow++}
53 | while(sheet.getRange(lastRow,column).getValue() != ''){}
54 | sheet.getRange(lastRow, column).setValue(users[i].primaryEmail)
55 | break;
56 | }
57 | }
58 | }
59 | pageToken = page.nextPageToken
60 | }while(pageToken){}
61 | }
62 |
63 | function WhereMyChromiesAt(){
64 | var chromies, page, ss, sheet, pageToken, lastCol, domain
65 | domain = "YOURDOMAIN"
66 | ss = SpreadsheetApp.openById("SPREADSHEET_ID")
67 | sheet = ss.getSheets()[0]
68 | lastCol = sheet.getLastColumn()
69 |
70 | do{
71 | page = AdminDirectory.Chromeosdevices.list("my_customer",
72 | {domain: domain,
73 | maxResults: 100,
74 | pageToken: pageToken
75 | })
76 | chromies = page.chromeosdevices
77 | for (var i in chromies){
78 | var column, lastRow, chromieOrg, j
79 | column = 1
80 | lastRow = 1
81 | chromieOrg = chromies[i].orgUnitPath
82 | for (column ; column < lastCol; column++){
83 | var orgPath = sheet.getRange(2, column).getValue()
84 | if (chromieOrg === orgPath){
85 | do{lastRow++}
86 | while(sheet.getRange(lastRow,column).getValue() != ''){}
87 | sheet.getRange(lastRow, column).setValue(chromies[i].macAddress)
88 | break;
89 | }
90 | }
91 | }
92 | pageToken = page.nextPageToken
93 | }while(pageToken){}
94 | }
95 |
--------------------------------------------------------------------------------
/Sync-OU-to-Group/README.md:
--------------------------------------------------------------------------------
1 | ##Sync OU to Group
2 | ####This Script Requires AdminSDK to be enabled in order to work.
3 |
4 | ##Setup
5 | ####All files are saved in a single Google Apps Script project as separate script files.
6 | First - Change all instances of "SPREADSHEET_ID" to the ID of a new Spreadsheet which you have edit privileges to.
7 |
8 | Second - Change the array a[] within the file SyncGroups.gs to match a Comma Separated List of the Groups you're wanting to sync. Example: a = ["Class of 2016", "Class of 2017", "Class of 2018"]
9 |
10 | ####This script will not create any new groups or OUs. All groups and OUs must be created beforehand.
11 | ##Execution
12 | Once all setup changes have been made, Start by running the functions in ImportOU.gs - importOUs(), WhereMyUsersAt(), WhereMyChromiesAt() [optional]. These functions will import all user and chrome device information necessary for the other functions to execute into the defined Spreadsheet.
13 |
14 | After OU, User, and Chrome information has been imported - run the function within ImportGroups.gs - getAllGroupUsers(). This will import the Groups, their names and current members into the second Sheet of the Spreadsheet.
15 |
16 | Once the Groups have been imported, execute the function within SyncGroups.gs - syncGroups().
17 |
18 | This is an extremely long process, and will only sync around 3-4 groups at any given time, based on the number of users. This is the reason that the array a[] is defined. Upon completion, make sure that all targeted groups were synced and that the execution didn't time out. In the event that the script timed out, remove the Groups from a[] which completed and re-run the syncGroup() function.
19 |
--------------------------------------------------------------------------------
/Sync-OU-to-Group/SyncGroup.gs:
--------------------------------------------------------------------------------
1 | function syncGroup(a,b){
2 | var ss = SpreadsheetApp.openById("SPREADSHEET_ID")
3 | a = ["Class of 2022"]
4 | var numRows = ss.getSheets()[0].getMaxRows()
5 | var numColumns = ss.getSheets()[0].getMaxColumns()
6 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
7 | var page, pageToken
8 | var groups = new Array(), newMembers = new Array();
9 | //get all Groups
10 | do{
11 | page = AdminDirectory.Groups.list({
12 | domain: domain,
13 | maxResults: 100,
14 | pageToken: pageToken
15 | });
16 | for (var i in page.groups){
17 | groups.push(page.groups[i])
18 | }
19 | pageToken = page.nextPageToken
20 | }while(pageToken){}
21 | //remove all users from Target Group
22 | for (var i in a){
23 | for (var j in groups){
24 | if (groups[j].name == a[i]){
25 | var groupMembers = AdminDirectory.Members.list(groups[j].id).members
26 | for (var k in groupMembers){
27 | try{
28 | AdminDirectory.Members.remove(groups[j].email, groupMembers[k].email)
29 | // Logger.log("%s removed from %s",groupMembers[k].email,groups[j].email)
30 | }
31 | catch(err){Logger.log(err.message)}
32 | }
33 | //Repopulate Groups with new Members
34 | newMembers = getNewUsers(a[i])
35 | var l = 1 // skip the first line
36 | do {
37 | var userEmail = newMembers[l]
38 | var resource = {email: userEmail,
39 | role: 'MEMBER'}
40 | try{
41 | AdminDirectory.Members.insert(resource,groups[j].email)
42 | Logger.log("%s added to group %s",userEmail,groups[j].email)
43 | }
44 | catch(err){Logger.log(err.message)}
45 | l++;
46 | }
47 | while(l < newMembers.length){}
48 | }
49 | }
50 | }
51 | //Update Groups in Spreadsheet
52 | getAllGroupUsers()
53 | }
54 |
--------------------------------------------------------------------------------
/Zebra/Build-A-Box.gs:
--------------------------------------------------------------------------------
1 | function getPenaltyBoxes(OUs,searchFor){
2 | if (!OUs){
3 | OUs = AdminDirectory.Orgunits.list("my_customer", {domain:domain, type:"all"}).organizationUnits
4 | }
5 | var that = new Array()
6 | if (!searchFor){
7 | searchFor = "/Penalty Box"
8 | }
9 | for (i in OUs){
10 | var re = new RegExp(searchFor+"$")
11 | if (re.test(OUs[i].orgUnitPath,"i")){
12 | that.push(OUs[i])
13 | }
14 | }
15 | return that
16 | }
17 |
18 | function buildABox(){
19 | var RootOuId, PenaltyBox, PenaltyBoxOU, PenaltyBoxId = "", UserOuNames, reply
20 | RootOuId = AdminDirectory.Orgunits.list("my_customer", {domain:domain, type:"children"}).organizationUnits[0].parentOrgUnitId
21 | while(PenaltyBoxId === ""){
22 | if (PenaltyOUSheet.getRange("A2").getValue() != ""){
23 | PenaltyBoxId = PenaltyOUSheet.getRange("A2").getValue()
24 | break
25 | }
26 | Logger.log("No ID Defined - Checking for existing Penalty Box")
27 | PenaltyBox = getPenaltyBoxes(AdminDirectory.Orgunits.list("my_customer", {domain:domain, type:"children"}).organizationUnits)
28 | if (PenaltyBox.length == 1){
29 | PenaltyOUSheet.getRange("A2").setValue(PenaltyBox[0].orgUnitId)
30 | Logger.log(PenaltyBox[0].orgUnitId)
31 | PenaltyBoxId = PenaltyBox[0].orgUnitId
32 | break
33 | }
34 | //Do you want to create New OrgUnit named "PenaltyBox" (Yes) or use an existing Org Unit (No)?
35 | reply = "Yes"
36 | if (reply == "Yes"){
37 | var resource = {name: "Penalty Box",
38 | parentOrgUnitId: RootOuId,
39 | description: "OU for users restricted for one reason or another -- Created by Zebra"}
40 | var PenaltyBoxOU = AdminDirectory.Orgunits.insert(resource, "my_customer")
41 | PenaltyOUSheet.getRange("A2").setValue(PenaltyBoxOU.orgUnitId)
42 | break
43 | }
44 | if (reply == "No"){
45 | //Choose and existing OU to use as a Penalty Box :
46 | PenaltyOUSheet.getRange("A2").setValue("/*OU ID*/")
47 | break
48 | }
49 | }
50 | // Logger.log("Using OU with Name %s and ID %s",AdminDirectory.Orgunits.get("my_customer", [PenaltyBoxId]).name, PenaltyBoxId)
51 | var lastRow = PenaltyOUSheet.getLastRow()
52 | for (var j =2; j < lastRow; j++){
53 | var NewBox = getPenaltyBoxes(AdminDirectory.Orgunits.list("my_customer",
54 | {domain:domain, type:"all"}).organizationUnits,
55 | PenaltyOUSheet.getRange("B"+j).getValues())
56 | try{
57 | PenaltyOUSheet.getRange("C"+j).setValue(NewBox[0].name)
58 | PenaltyOUSheet.getRange("D"+j).setValue(NewBox[0].orgUnitId)
59 | }
60 | catch(err){
61 | PenaltyOUSheet.getRange("C"+j).setValue("Error: Cannot find Org")
62 | updateAuditLog([new Date(), Session.getEffectiveUser(), err])}
63 | }
64 | createOU(PenaltyBoxId, PenaltyOUSheet)
65 |
66 | // internal functions
67 | function createOU(ParentId, Sheet){
68 | var lastRow = Sheet.getLastRow();
69 | var boxes = getPenaltyBoxes();
70 | var children = [];
71 | for (i in boxes){
72 | var child = boxes[i];
73 | children.push(child)
74 | };
75 | var re = new RegExp(children.organizationUnits)
76 | // check to see if OU exists. If TRUE, copy the OrgUnitId to the PenaltyBox ID column; If FALSE, create new OrgUnit, the record;
77 | for(i=2; i < lastRow; i++){
78 | try{
79 | var value = Sheet.getRange("C"+i).getValue()
80 | Logger.log("%s : %s", value, re)
81 | // check to see if OU exists.
82 | if (/Error|Penalty/i.test(value)){
83 | continue;}
84 | if (re.test(value)){
85 | Logger.log("%s Exists",value)
86 | Sheet.getRange("C"+i).setValue("/Penalty Box/"+value)
87 | continue;}
88 | else{
89 | var resource = {name: value,
90 | description: "Penalty Box -- created by Zebra",
91 | parentOrgUnitId: ParentId}
92 | var NewChild = AdminDirectory.Orgunits.insert(resource, 'my_customer')
93 | Sheet.getRange("E"+i).setValue(NewChild.orgUnitPath)
94 | Sheet.getRange("F"+i).setValue(NewChild.orgUnitId)
95 | };}
96 | catch(err){updateAuditLog([new Date(), Session.getEffectiveUser(), "Error in Build-A-Box",err])}
97 | }}
98 | }
99 |
100 | function clearPenaltyBoxes(ParentID){
101 | if (!ParentID){
102 | ParentID = PenaltyOUSheet.getRange("A2").getValue()
103 | }
104 | var children = AdminDirectory.Orgunits.list("my_customer", {
105 | domain: domain,
106 | orgUnitPath: ParentID,
107 | })
108 | for (i in children.organizationUnits){
109 | updateAuditLog([new Date(), Session.getEffectiveUser(),"Deleting "+children.organizationUnits[i].orgUnitPath,"Clear Penalty Box"])
110 | try{
111 | AdminDirectory.Orgunits.remove("my_customer", [children.organizationUnits[i].orgUnitId])
112 | }
113 | catch(err){updateAuditLog([new Date(),Session.getEffectiveUser(),"Error in Clearing Penalty Box - "+children.organizationUnits[i].orgUnitPath, err])}
114 | }
115 | PenaltyOUSheet.getRange("C2:G").clear()
116 | }
117 |
--------------------------------------------------------------------------------
/Zebra/README.md:
--------------------------------------------------------------------------------
1 | ##https://goo.gl/pPD6AB
2 | view only GAS-Editor
3 |
4 | #Zebra
5 | is a referee style application (hopefully addon) which allows Google Apps Administrators to delegate sending users to a pre-built Penalty Box OU. The idea being that the Penalty Box would have restricted settings and limited navigation capability. Users are sent there as part of some disciplinary action. The name is derived from my days watching our High School's hockey team and being kicked out of more than one match for chanting at the refs "Zebra zebra short and stout, find your head and pull it out."
6 |
7 | ##Setup
8 | Start by copying all the contained files into a single **Google Apps Script** project. Each .gs file can be compiled into a single script file or can be split into the files as outlined. **Enable the appropriate __Advanced Services__ to allow the script access to the AdminSDK**
9 |
10 | **Enable the "AdminSDK" in the Advanced Google Services and the Google Developers Console. The link to the Google Developers Console for this project will be found in the same popup menu as the Advanced Google Services.**
11 |
12 | Run the function **initialize()** found in the file Triggers.gs. If you are running the script on a new Spreadsheet without a form attached, you will have to run the function twice (x2) - the first time will create the form and attach it to the Spreadsheet. The second time will complete the rest of the configuration.
13 |
14 | You can check the current progress of the installation by going to the "Status" sheet withing the Spreadsheet. An Editor to the form will then have to populate the Scope for each staff member. Without this, users will be able to submit the form, but nothing will happen other than an audit log will be created stating they weren't permitted to move the user.
15 |
16 | ~~***TODO:*** Upon final completion, send an email to the user with a shortened link to the **Google Form**.~~
17 |
18 | ##NOTE:
19 | Restrictions will still need to be set for the Penalty Box OU. **Failure to do so will result in _unrestricted access_ rather than restricted access**. It is recommended that the settings are made to the *Parent Penalty Box OU* with exceptions made to the children OUs.
20 |
21 | ##End User usage (What the Teachers See)
22 | Navigate to the __live version__ of the **Zebra Form**, created in the installation process. Users select their email address (used for verification later), where the users are located at and how long to leave them in the Penalty Box from a Dropdown box. On the next page, they select which students to move, and submit the form.
23 |
24 | Upon submission, a trigger will fire, executing the **redCard()** function, sending the user to the penalty box for their OrgUnit. Once the duration has passed, the user will be placed back into their former OU.
25 |
26 | ##Scope
27 | Defining a scope will restrict which OUs authorized staff will be able to referee. *Seems to be working, but needs verification*. By Default, Staff's scope is empty. Should there be a desire, this setting could be change. The Scope cells support | (pipes) and all children OUs inherrit their parent scope settings.
28 |
29 | ##Audit Log
30 | Because this involves moving users and executes the redCard() __function as the GAFE Administrator__ from Google's Reporting perspective, *Auditing* is important. The audit log will be updated every time a user is moved either by the submission of the script or when their duration runs out. Errors, such as if there is a username mismatch or an attempted scope violation, are also logged without executing the redCard() function. All other errors are also logged.
31 |
32 | #Functions:
33 | **Triggers.gs**
34 | _Initialize()_ - runs all functions in proper order in. Has built-in checks to make sure that if the execution goes longer than planned it can pickup where it left off by re-running the Initialize() function.
35 |
36 | _installOnEdit()_ - is one of the triggers that is **not** installed by the Initialize() function (perhaps at a later date). This function installs an "onEdit" trigger to the Spreadsheet where, when the spreadsheet is edited, the Form is updated. This was removed due to the excessive number of Edits taking place on the Spreadsheet. __A range limiter will need to be added to the importOptionsToForm() function.__
37 |
38 | _installOnSubmit()_ - attaches the Form submit function to the redCard() function.
39 |
40 | _installTimeTrigger()_ - attaches a trigger that runs checkExpiration() every 3 minutes (can change to every minute if needed)
41 |
42 | _checkExpiration()_ - checks to see if any *Current Offenders* should be removed from the Penalty Box.
43 |
44 | **Build-A-Box.gs**
45 | _buildABox()_ - creates a new Penalty Box OU at the Root of your OU Structure unless one exists with that name, in which case, it uses that OU. This function should also create sub-OUs based on where your Users are found. A matrix is created, associating the original OU and the penalty box sub-OU. These values are used toput users back into their original OU when their time in the Penalty Box is over.
46 |
47 | _clearPenaltyBox()_ - removes all sub-OUs of the root defined Penalty Box. If there are users in the Penalty Box at the time, that individual sub-OU will not be deleted.
48 |
49 | **redCard.gs** is in the *BETA* phase.
50 | _redCard()_ - is the function which is attached to the onSubmit() trigger for the associated form. When triggered, if the SessionUser has been authorized in the *scope* and selected their name in the drop-down menu, The selected students will be moved into the appropriate *Penalty Box OU*. The AuditLog is triggered and records a line for every student moved, or if any errors occur.
51 |
52 | _updateAuditLog()_ - basic function to update range of the Audit Log Sheet with pertinent information.
53 |
54 | **importFromGoogle.gs**
55 | _updateStaff()_ - pulls data from the AdminDirectory inlcuding OU Structure, Staff Email addresses and stores the information statically on the Staff Sheet. This is later used to build populate the Google Form which is used to deliver the User Experience.
56 |
57 | _updateStudents()_ - same as updateStaff(), except for students.
58 |
59 | **updateForm.gs**
60 | _importOptionsToForm(form)_ - builds the form structure, populates questsions, changes user navigation based on answer... everything to make the End User's experience as simplified as possible.
61 |
62 | _clearForm(form)_ removes all items from the existing form. Former submissions are still stored and upon new creation will be listed in a separate column in the Form Response page. -- basically there to make my life easier during development.
63 |
64 | **scope.gs**
65 | _getScope(scope)_ - used by the script to determine whether the Session User has permission to make the requested changes. **This may be enough where having the user select their email might not be necessary,** though selecting email would still be necessary if we wanted to limit their Building selections at a later date.
66 |
--------------------------------------------------------------------------------
/Zebra/Triggers.gs:
--------------------------------------------------------------------------------
1 | function Initialize() {
2 | //run checks to see what is present - execute next function in sequence;
3 | var status, staffCell, studentCell, buildingCell, formPopulateCell, submitCell, timeCell, editCell
4 |
5 | staffCell = statusSheet.getRange("D2")
6 | studentCell = statusSheet.getRange("D3")
7 | buildingCell = statusSheet.getRange("D4")
8 | formPopulateCell = statusSheet.getRange("D5")
9 | submitCell = statusSheet.getRange("D6")
10 | timeCell = statusSheet.getRange("D7")
11 | editCell = statusSheet.getRange("D8")
12 |
13 | var status = {
14 | staffImported: staffCell.getValue(),
15 | studentsImported: studentCell.getValue(),
16 | buildingsPopulated: buildingCell.getValue(),
17 | formPopulate: formPopulateCell.getValue(),
18 | submitTrigger: submitCell.getValue(),
19 | timeTrigger: timeCell.getValue(),
20 | onEditTrigger: editCell.getValue()
21 | }
22 | while (status.timeTrigger == ''){
23 | switch(true){
24 | case (status.staffImported == ''): //1
25 | updateStaff()
26 | staffCell.setValue("Staff Imported ✓")
27 | .setBackground("Green")
28 | .setHorizontalAlignment("center")
29 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Imported Staff: Success"])
30 | status.staffImported = staffCell.getValue()
31 | break;
32 | case (status.studentsImported == ''): //2
33 | updateStudents()
34 | studentCell.setValue("Students Imported ✓")
35 | .setBackground("Green")
36 | .setHorizontalAlignment("center")
37 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Imported Students: Success"])
38 | status.studentsImported = studentCell.getValue()
39 | break;
40 | case (status.buildingsPopulated == ''): //3
41 | var buildingsRange1 = PenaltyOUSheet.getRange("B2")
42 | .setValue('=Unique(FILTER(Students!B2:B,not(ARRAYFORMULA(REGEXMATCH(Students!B2:B, "Penalty")))))')
43 | var buildingsRange2 = staffSheet.getRange("D2")
44 | .setValue('=Unique(FILTER('+"'Penalty Box'!C2:C,not(ARRAYFORMULA(REGEXMATCH('Penalty Box'!C2:C,"+'"Penalty|Error")))))')
45 | buildABox()
46 | buildingCell.setValue("Penalty Box Created ✓")
47 | .setBackground("Green")
48 | .setHorizontalAlignment("center")
49 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Build-a-Box: Success"])
50 | status.buildingsPopulated = buildingCell.getValue()
51 | break;
52 | case (status.formPopulate == ''): //4
53 | importOptionsToForm(form)
54 | formPopulateCell.setValue("Zebra Form Updated ✓")
55 | .setBackground("Green")
56 | .setHorizontalAlignment("center")
57 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Updated Zebra Form: Success"])
58 | status.formPopulate = formPopulateCell.getValue()
59 | break;
60 | case (status.submitTrigger == ''): //5
61 | installOnSubmit()
62 | submitCell.setValue("Submit Trigger Installed ✓")
63 | .setBackground("Green")
64 | .setHorizontalAlignment("center")
65 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Installed Submit Trigger: Success"])
66 | status.submitTrigger = submitCell.getValue()
67 | break;
68 | case (status.timeTrigger == ''): //6
69 | installTimeTrigger()
70 | timeCell.setValue("Time Trigger Installed ✓")
71 | .setBackground("Green")
72 | .setHorizontalAlignment("center")
73 | updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Installed Time Trigger: Success"])
74 | status.timeTrigger = timeCell.getValue()
75 | break;
76 | // case (status.onEditTrigger == ''): //7
77 | // installOnEdit()
78 | // editCell.setValue("Edit Trigger Installed ✓")
79 | // .setBackground("Green")
80 | // .setHorizontalAlignment("center")
81 | // updateAuditLog([new Date(), Session.getActiveUser(), "Inital installation - Installed Time Trigger: Success"])
82 | // status.onEditTrigger = editCell.getValue()
83 | // break;
84 | }
85 | }
86 | var URL = form.getPublishedUrl()
87 | var HTML = ''
88 | HTML += '
is a referee style application (hopefully addon) which allows Google Apps Administrators to delegate sending users to a pre-built Penalty Box OU. The idea being that the Penalty Box would have restricted settings and limited navigation capability. Users are sent there as part of some disciplinary action. The name is derived from my days watching our High School\'s hockey team and being kicked out of more than one match for chanting at the refs "Zebra zebra short and stout, find your head and pull it out."
'
92 | HTML += '
Setup
'
93 | HTML += '
Start by copying all the contained files into a single Google Apps Script project. Each .gs file can be compiled into a single script file or can be split into the files as outlined. Enable the appropriate Advanced Services to allow the script access to the AdminSDK
'
94 | HTML += '
Enable the "AdminSDK" in the Advanced Google Services and the Google Developers Console. The link to the Google Developers Console for this project will be found in the same popup menu as the Advanced Google Services.
'
95 | HTML += '
Run the function initialize() found in the file Triggers.gs. If you are running the script on a new Spreadsheet without a form attached, you will have to run the function twice (x2) - the first time will create the form and attach it to the Spreadsheet. The second time will complete the rest of the configuration.
'
96 | HTML += '
You can check the current progress of the installation by going to the "Status" sheet withing the Spreadsheet. An Editor to the form will then have to populate the Scope for each staff member. Without this, users will be able to submit the form, but nothing will happen other than an audit log will be created stating they weren\'t permitted to move the user.
'
97 | HTML += '
TODO: Upon final completion, send an email to the user with a shortened link to the Google Form.
'
98 | HTML += '
NOTE:
'
99 | HTML += '
Restrictions will still need to be set for the Penalty Box OU. Failure to do so will result in unrestricted access rather than restricted access. It is recommended that the settings are made to the Parent Penalty Box OU with exceptions made to the children OUs.
'
100 | HTML += '
End User usage (What the Teachers See)
'
101 | HTML += '
Navigate to the live version of the Zebra Form, created in the installation process. Users select their email address (used for verification later), where the users are located at and how long to leave them in the Penalty Box from a Dropdown box. On the next page, they select which students to move, and submit the form.
'
102 | HTML += '
Upon submission, a trigger will fire, executing the redCard() function, sending the user to the penalty box for their OrgUnit. Once the duration has passed, the user will be placed back into their former OU.
'
103 | HTML += '
Scope
'
104 | HTML += '
Defining a scope will restrict which OUs authorized staff will be able to referee. Seems to be working, but needs verification. By Default, Staff\'s scope is empty. Should there be a desire, this setting could be change. The Scope cells support | (pipes) and all children OUs inherrit their parent scope settings.
'
105 | HTML += '
Audit Log
'
106 | HTML += '
Because this involves moving users and executes the redCard() function as the GAFE Administrator from Google\'s Reporting perspective, Auditing is important. The audit log will be updated every time a user is moved either by the submission of the script or when their duration runs out. Errors, such as if there is a username mismatch or an attempted scope violation, are also logged without executing the redCard() function. All other errors are also logged.
'
107 | HTML += '
Functions:
'
108 | HTML += '
Triggers.gs '
109 | HTML += 'Initialize() - runs all functions in proper order in. Has built-in checks to make sure that if the execution goes longer than planned it can pickup where it left off by re-running the Initialize() function.
'
110 | HTML += '
installOnEdit() - is one of the triggers that is not installed by the Initialize() function (perhaps at a later date). This function installs an "onEdit" trigger to the Spreadsheet where, when the spreadsheet is edited, the Form is updated. This was removed due to the excessive number of Edits taking place on the Spreadsheet. A range limiter will need to be added to the importOptionsToForm() function.
'
111 | HTML += '
installOnSubmit() - attaches the Form submit function to the redCard() function.
'
112 | HTML += '
installTimeTrigger() - attaches a trigger that runs checkExpiration() every 3 minutes (can change to every minute if needed)
'
113 | HTML += '
checkExpiration() - checks to see if any Current Offenders should be removed from the Penalty Box.
'
114 | HTML += '
Build-A-Box.gs '
115 | HTML += 'buildABox() - creates a new Penalty Box OU at the Root of your OU Structure unless one exists with that name, in which case, it uses that OU. This function should also create sub-OUs based on where your Users are found. A matrix is created, associating the original OU and the penalty box sub-OU. These values are used toput users back into their original OU when their time in the Penalty Box is over.
'
116 | HTML += '
clearPenaltyBox() - removes all sub-OUs of the root defined Penalty Box. If there are users in the Penalty Box at the time, that individual sub-OU will not be deleted.
'
117 | HTML += '
redCard.gs is in the BETA phase. '
118 | HTML += 'redCard() - is the function which is attached to the onSubmit() trigger for the associated form. When triggered, if the SessionUser has been authorized in the scope and selected their name in the drop-down menu, The selected students will be moved into the appropriate Penalty Box OU. The AuditLog is triggered and records a line for every student moved, or if any errors occur.
'
119 | HTML += '
updateAuditLog() - basic function to update range of the Audit Log Sheet with pertinent information.
'
120 | HTML += '
importFromGoogle.gs '
121 | HTML += 'updateStaff() - pulls data from the AdminDirectory inlcuding OU Structure, Staff Email addresses and stores the information statically on the Staff Sheet. This is later used to build populate the Google Form which is used to deliver the User Experience.
'
122 | HTML += '
updateStudents() - same as updateStaff(), except for students.
'
123 | HTML += '
updateForm.gs '
124 | HTML += 'importOptionsToForm(form) - builds the form structure, populates questsions, changes user navigation based on answer... everything to make the End User\'s experience as simplified as possible.
'
125 | HTML += '
clearForm(form) removes all items from the existing form. Former submissions are still stored and upon new creation will be listed in a separate column in the Form Response page. -- basically there to make my life easier during development.
'
126 | HTML += '
scope.gs '
127 | HTML += 'getScope(scope) - used by the script to determine whether the Session User has permission to make the requested changes. This may be enough where having the user select their email might not be necessary, though selecting email would still be necessary if we wanted to limit their Building selections at a later date.
'
128 |
129 | GmailApp.sendEmail(Session.getEffectiveUser(), "ZEBRA Form Information", "Here's the link to your ZEBRA form: "+URL , {replyTo: "gales@wgsd.us",htmlBody:HTML})
130 | }
131 | function installOnEdit(){
132 | ScriptApp.newTrigger("importOptionsToForm")
133 | .forSpreadsheet(ss)
134 | .onEdit()
135 | .create()
136 | }
137 | function installOnSubmit(){
138 | ScriptApp.newTrigger("redCard")
139 | .forForm(form)
140 | .onFormSubmit()
141 | .create()
142 | }
143 | function installTimeTrigger(){
144 | ScriptApp.newTrigger("checkExpiration")
145 | .timeBased()
146 | .everyMinutes(5)
147 | .create()
148 | }
149 |
150 | function checkExpiration(){
151 | if (currentBoxUsersSheet.getLastRow() > 1){
152 | var sheet = auditLogSheet
153 | var LastRow = sheet.getLastRow()
154 | var range = sheet.getRange("A2:G"+LastRow)
155 | for (i = 0; i < range.getValues().length; i++){
156 | var rowIndex = new Number(i)+2
157 | var isExpired = range.getValues()[i][6]
158 | var student = range.getValues()[i][0]
159 | if (!isExpired){continue}
160 | else {
161 | //Add Marker to show that the line has been previously processed. (Background Color, etc)
162 |
163 | var status = isRedCarded(student)
164 | if (status != false){
165 | Logger.log(status.newLocationId)
166 | var resource = {orgUnitPath: status.newLocation}
167 | AdminDirectory.Users.update(resource, status.email)
168 | updateAuditLog([student,"Zebra - Times Up",status.newLocation,"Indefinitely",new Date(),"",
169 | "=IF(NOT(ISBLANK(F"+LastRow+1+")),(F"+LastRow+1+"-NOW())<0,F"+LastRow+1+")"])
170 | }
171 | }
172 | }
173 | updateStudents()
174 | }
175 |
176 | //internal functions
177 | function isRedCarded(student){
178 | student = {email : student,
179 | currentLocation : '',
180 | currentLocationId : '',
181 | newLocation : '',
182 | newLocationId : ''}
183 |
184 | var currentOffenders = currentBoxUsersSheet.getRange("A2:C"+currentBoxUsersSheet.getLastRow()).getValues()
185 | var re = new RegExp(student.email)
186 | if (re.test(currentOffenders)){
187 | var j=0
188 | while(j < currentOffenders.length){
189 | if (currentOffenders[j][0] == student.email){
190 | student.currentLocation = currentOffenders[j][1]
191 | var LastRow = PenaltyOUSheet.getLastRow()
192 | var matrix = PenaltyOUSheet.getRange("B2:G"+LastRow).getValues()
193 | for (var k = 0; k < matrix.length; k++){
194 | if (matrix[k][3] == student.currentLocation){
195 | student.currentLocationId = matrix[k][4]
196 | student.newLocation = matrix[k][0]
197 | student.newLocationId = matrix[k][2]
198 | return student
199 | }
200 | }
201 | }
202 | j++;
203 | }
204 | }
205 | return false
206 | }//end isRedCarded()
207 | }
208 |
--------------------------------------------------------------------------------
/Zebra/importFromGoogle.gs:
--------------------------------------------------------------------------------
1 | //"Zebra zebra short and stout find your head and pull it out" - Hockey croud chant directed at the officials, especially when the croud disagrees with a call.
2 | var ss = SpreadsheetApp.openById("SPREADSHEET_ID")
3 |
4 | var domain = Session.getEffectiveUser().getEmail().split("@")[1]
5 | var statusSheet, form
6 | if (ss.getFormUrl() == null){
7 | form = FormApp.create("Zebra")
8 | .setCollectEmail(true)
9 | .setProgressBar(false)
10 | .setRequireLogin(true)
11 | .setDestination(FormApp.DestinationType.SPREADSHEET, ss.getId())
12 | }
13 | else{form = FormApp.openByUrl(ss.getFormUrl())}
14 |
15 | if (ss.getSheets()[1].getRange("A1").getValue() != 'Status'){
16 | ss.getSheets()[1].setName("Status")
17 | .getRange("A1:C8")
18 | .setValues([["Status",'',''],["Status",'',"Staff"],["Staff",'',"Student"],["Students",,"building"],["Penalty Box",'',"formPopulated"],
19 | ["Current Offenders",'',"TimeTrigger"],["Audit Log",'',"EditTrigger"],["Form ID",'',""]])
20 | }
21 | statusSheet = ss.getSheetByName("Status")
22 | ss.setActiveSheet(ss.getSheets()[(ss.getSheets().length)-1])
23 |
24 | while (ss.getSheets().length < 7){
25 | var newSheet = ss.insertSheet()
26 | var range = statusSheet.getRange(newSheet.getIndex(),2, 1, 1)
27 | range.setValue(newSheet.getSheetId())
28 | newSheet.setName(statusSheet.getRange(newSheet.getIndex(),1, 1, 1).getValue())
29 | }
30 |
31 | var staffSheet = ss.getSheetByName("Staff")
32 | var studentsSheet = ss.getSheetByName("Students")
33 | var PenaltyOUSheet = ss.getSheetByName("Penalty Box")
34 | var currentBoxUsersSheet = ss.getSheetByName("Current Offenders")
35 | var auditLogSheet = ss.getSheetByName("Audit Log")
36 | try{
37 | var formIdCell = statusSheet.getRange("B8")
38 | formIdCell.setValue(form.getId())
39 | PenaltyOUSheet.getRange("A1:F1").setValues([["Root PenaltyBox OU ID","User OUs","User OU Name", "User OU ID","PenaltyBoxOU","PenaltyBox ID for OU"]]).setBackground("Gray")
40 | PenaltyOUSheet.getRange("G1:G").setFontColor("White")
41 | staffSheet.getRange("A1:E1").setValues([["Staff","OUs","Scope","Building Description","RegExp(OU)"]]).setBackground("Gray")
42 | studentsSheet.getRange("A1:C1").setValues([["Students","OUs","Penalty Box"]]).setBackground("Gray")
43 | auditLogSheet.getRange("A1:D1").setValues([["Student","User","Description","TimeStamp"]]).setBackground("Gray")
44 | var sheet1 = ss.getSheetByName('Sheet1')
45 |
46 | if (formIdCell.getValue() != ''){
47 | var form = FormApp.openById(formIdCell.getValue())
48 | }
49 |
50 | } catch(err){Logger.log([new Date(),Session.getEffectiveUser(),"Error starting script:",JSON.stringify(err)])}
51 |
52 | function updateStaff() {
53 | var limit = "staff", exclude = ''
54 | var excludeList = ["Generic","Suspended","Outgoing"] //import from UI, Store in Sheet
55 | for (i in excludeList){
56 | exclude += excludeList[i] + "|"
57 | }
58 | exclude = exclude.substring(0,exclude.length-1)
59 | var sheet, staff = new Array(),limitUsers = new RegExp(limit,"i"),excludeUsers = new RegExp(exclude,"i"), page, pageToken, user
60 | sheet = staffSheet
61 | var range = sheet.getRange("A2:B")
62 | try{
63 | range.clear()
64 | }
65 | catch(err){updateAuditLog([new Date(),"Error clearing Staff sheet",err])}
66 | do{
67 | page = AdminDirectory.Users.list({
68 | maxResults:100,
69 | domain:domain,
70 | sortBy:"familyName",
71 | pageToken:pageToken
72 | })
73 | for (i in page.users){
74 | user = page.users[i]
75 | if (limitUsers.test(user.orgUnitPath)){
76 | if (excludeUsers.test(user.orgUnitPath)){
77 | continue
78 | }
79 | staff.push(user)
80 | }}
81 | pageToken = page.nextPageToken
82 | }while(pageToken){}
83 | for (i in staff){
84 | sheet.appendRow([staff[i].primaryEmail,staff[i].orgUnitPath])
85 | }
86 | sheet.getRange("A2:B").sort(2)
87 | //update Scope, Buildings and RegExp(OU)
88 | var buildingsRange = staffSheet.getRange("D2:D").setValues(PenaltyOUSheet.getRange("C2:C").getValues())
89 | var regexRange = staffSheet.getRange("E2:E")
90 |
91 |
92 | // importOptionsToForm()
93 | }
94 | function updateStudents(){
95 | var limit = "Student|Penalty", exclude = ''
96 | var excludeList = ["Generic","Suspended","Outgoing","Graduated"] //import from UI, Store in Sheet
97 | for (i in excludeList){
98 | exclude += excludeList[i] + "|"
99 | }
100 | exclude = exclude.substring(0,exclude.length-1)
101 |
102 | var sheet, students = new Array(),limitUsers = new RegExp(limit,"i"),excludeUsers = new RegExp(exclude,"i"), page, pageToken, user
103 | sheet = studentsSheet
104 | var range = sheet.getRange("A2:D")
105 | //need to find a more elegant way to update... for now, clear() and repopulate
106 | try{
107 | range.clear()
108 | }
109 | catch(err){updateAuditLog([new Date(),"Error clearing Student sheet",err])}
110 | do{
111 | page = AdminDirectory.Users.list({
112 | maxResults:100,
113 | domain:domain,
114 | sortBy:"familyName",
115 | pageToken:pageToken
116 | })
117 | for (i in page.users){
118 | user = page.users[i]
119 | if (limitUsers.test(user.orgUnitPath,i)){
120 | if (excludeUsers.test(user.orgUnitPath,i)){
121 | continue
122 | }
123 | students.push(user)
124 | }}
125 | pageToken = page.nextPageToken
126 | }while(pageToken){}
127 | //repopulate
128 | for (i in students){
129 | sheet.appendRow([students[i].primaryEmail,students[i].orgUnitPath,/Penalty/i.test(students[i].orgUnitPath)])
130 | }
131 | //and sort by OU
132 | sheet.getRange("A2:D").sort(2)
133 |
134 | //check to see if Student OUs have Updated
135 | currentBoxUsersSheet.getRange("A1").setValue('=QUERY(Students!A:D,"select A,B,C,D where C = true")')
136 | var LastRow = PenaltyOUSheet.getLastRow()
137 | var setNewValues = PenaltyOUSheet.getRange("G2").setValue('=Unique(FILTER(Students!B2:B,not(ARRAYFORMULA(REGEXMATCH(Students!B2:B, "Penalty")))))').getValues()
138 | var originalValues = PenaltyOUSheet.getRange("B2:B"+LastRow)
139 | var newValues = PenaltyOUSheet.getRange("G2:G"+LastRow)
140 | if (originalValues.getValues().join() != newValues.getValues().join()){
141 | // newValues.copyValuesToRange(PenaltyOUSheet, 3, 2, 2, LastRow)
142 | updateAuditLog([new Date(),"Student Org Units Updated "])
143 | //Need to make sure that PenaltyBoxes still line up!
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Zebra/redCard.gs:
--------------------------------------------------------------------------------
1 | function redCard(e){
2 | //executes on form submit
3 | try{
4 | // Utilities.sleep(1500);
5 | if ((e == undefined) || (typeof e == "object")){
6 | if ((typeof e == "object")){
7 | var check = e.response.getEditResponseUrl()};
8 | var len = (form.getResponses().length-1)
9 | }
10 | var $response = getResponses(form,len);
11 | if ((check != $response.editUrl) && (check != undefined)){
12 | if(e > 0){
13 | e--; redCard(e)}
14 | else {throw("Error: something screwed up")}
15 | }
16 | Logger.log("Check passed - referencing the correct response");
17 | }
18 | catch(err){updateAuditLog([new Date(),"Error in phase 1:",err]);return false;}
19 |
20 | try{
21 | //begin checks
22 | if ($response.email == $response.sessionUser){ //ensure sessionUser is who they say they are.
23 | var email = $response.email, sheet = ss.getSheetByName("Staff"), rowLen = sheet.getLastRow()
24 | var users = sheet.getRange(1,1,rowLen).getValues(), userIndex
25 | for (i in users){
26 | if(users[i] == email){
27 | userIndex = i; userIndex++;
28 | break
29 | }
30 | }
31 | var scope = sheet.getRange(userIndex, 3).getValue()
32 | if (scope === ''){
33 | throw("Scope for "+$response.sessionUser+" is not set.")}
34 | var authorize = getScope(scope)
35 | for (i in $response.redCard){
36 | var re = new RegExp($response.redCard[i])
37 | if(re.test(authorize)){
38 | //Student // session user //duration
39 | moveUser($response.redCard[i], email, $response.duration)
40 | }
41 | else{throw($response.sessionUser+" is not authorized to RedCard selected users: "+ $response.redCard)}
42 | }
43 | }
44 | else{throw($response.sessionUser+" entered incorrect email address")}
45 | }
46 | catch(err){updateAuditLog([new Date(),"Error in phase 2:",err]);return false}
47 | //if moving the student was successful, update the student sheet
48 | updateStudents()
49 |
50 | //internally used functions
51 | function moveUser(student, user, duration){
52 | try{
53 | var sheet = studentsSheet, numRows = sheet.getLastRow(), students = sheet.getRange(1,1,numRows).getValues(), studentIndex, endTime
54 | for (i in students){
55 | if(students[i] == student){
56 | studentIndex = i; studentIndex++;
57 | break
58 | }
59 | }
60 | var studentOU = sheet.getRange(studentIndex,2).getValue()
61 | var PenaltyBox = PenaltyOUSheet.getRange("C2:C"+PenaltyOUSheet.getLastRow()).getValues()
62 | var PenaltyBoxIndex
63 | for (i in PenaltyBox){
64 | if ($response.building == PenaltyBox[i]){
65 | PenaltyBoxIndex = (new Number(i) + 2);
66 | break;
67 | }
68 | }
69 | var PenaltyBoxId = PenaltyOUSheet.getRange("F"+PenaltyBoxIndex).getValue()
70 | var OrgUnitPath = AdminDirectory.Orgunits.get('my_customer', [PenaltyBoxId])
71 | var resource = {orgUnitPath: OrgUnitPath.orgUnitPath}
72 | if (/[0-9]{2}/.test(duration)){
73 | endTime = "=E"+(auditLogSheet.getLastRow()+1)+"+("+duration.match(/[0-9]{1,2}/)+"*(1/24/60))"
74 | }
75 | else if (/[0-9]{1}/.test(duration)){
76 | endTime = "=E"+(auditLogSheet.getLastRow()+1)+"+("+duration.match(/[0-9]{1}/)+"*(1/24))"
77 | }
78 | else{endTime = ""}
79 | AdminDirectory.Users.update(resource, student)
80 | var LastRow = new Number(auditLogSheet.getLastRow())+1
81 | updateAuditLog([student, user, resource.orgUnitPath, duration, $response.timeStamp,
82 | endTime,"=IF(NOT(ISBLANK(F"+LastRow+1+")),(F"+LastRow+1+"-NOW())<0,F"+LastRow+1+")"])
83 | }
84 | catch(err){updateAuditLog([new Date(),"Error moving "+student,$response.redCard[i], err])}
85 | }
86 | function getResponses(f, response_number){
87 | if (f == undefined){
88 | var f = form
89 | }
90 | if (response_number == undefined){
91 | response_number = (f.getResponses().length-1)
92 | }
93 | var formResponses = f.getResponses();
94 | var $responses = new Array;
95 | for (i = (response_number) ; i < (response_number+1); i++) {
96 | var formResponse = formResponses[response_number];
97 | var formResponseEditUrl = formResponse.getEditResponseUrl();
98 | var itemResponses = formResponse.getItemResponses();
99 | var sessionUser = formResponse.getRespondentEmail();
100 | var timeStamp = formResponse.getTimestamp();
101 | }
102 | var redCardUsers = new Array()
103 | for (i in itemResponses){
104 | switch(true){
105 | case (itemResponses[i].getItem().getTitle() == "Select your email from the list"):
106 | var email = itemResponses[i].getResponse()
107 | break;
108 | case(itemResponses[i].getItem().getTitle() == "How long shall we keep the user(s) in the Penalty Box?"):
109 | var duration = itemResponses[i].getResponse()
110 | break;
111 | case(itemResponses[i].getItem().getTitle() == "Where are the student(s) located"):
112 | var building = itemResponses[i].getResponse()
113 | break;
114 | default :
115 | redCardUsers.push(itemResponses[i].getResponse())
116 | break;
117 | }
118 | }
119 | var that={email:email,
120 | timeStamp: timeStamp,
121 | duration:duration,
122 | building:building,
123 | redCard:redCardUsers[0],
124 | editUrl:formResponseEditUrl,
125 | sessionUser:sessionUser}
126 | return that
127 | }
128 | }
129 | function updateAuditLog(payload){
130 | var sheet = auditLogSheet
131 | sheet.appendRow(payload)
132 | }
133 |
--------------------------------------------------------------------------------
/Zebra/scope.gs:
--------------------------------------------------------------------------------
1 | function getScope(scope){
2 | var re = new RegExp(scope), page, pageToken, students = new Array(), student
3 |
4 | do{
5 | page = AdminDirectory.Users.list({
6 | maxResults:100,
7 | sortBy:"familyName",
8 | domain:domain,
9 | pageToken:pageToken
10 | })
11 | for (i in page.users){
12 | student = page.users[i]
13 | if (re.test(student.orgUnitPath)){
14 | students.push(student.primaryEmail)
15 | }}
16 | pageToken = page.nextPageToken
17 | }
18 | while(pageToken){}
19 | return students
20 | }
21 |
--------------------------------------------------------------------------------
/Zebra/updateForm.gs:
--------------------------------------------------------------------------------
1 | function importOptionsToForm(form){
2 | var items = form.getItems()
3 | var pages = form.getItems(FormApp.ItemType.PAGE_BREAK)
4 | var pagesArray = new Array()
5 | var staff = getStaff()
6 | var buildings = getBuildings()
7 | var buildingChoices = new Array()
8 | var students = getStudents()
9 |
10 | if (items.length < 3){
11 | //initial setup
12 | var email = form.addListItem()
13 | .setChoiceValues(staff)
14 | .setTitle("Select your email from the list")
15 | var class = form.addListItem()
16 | .setTitle("Where are the student(s) located")
17 | var time = form.addListItem()
18 | .setChoiceValues(["30 Minutes","45 Minutes","1 hour","2 hours","Indefinitely"]) //pull from Spreadsheet or User Input.
19 | .setTitle("How long shall we keep the user(s) in the Penalty Box?")
20 | }
21 | else{
22 | var email = items[0].asListItem()
23 | var class = items[1].asListItem()
24 | var time = items[2].asListItem()
25 | email.setChoiceValues(staff)
26 | }
27 | for (i in pages){
28 | pagesArray.push(pages[i].getTitle())
29 | }
30 | for (i=0;i