SSN Remediation Can’t Come Soon Enough..

This June, we’re finally, finally going to stop using SSN as a primary key at UMBC, and frankly, the big day can’t come soon enough. And it’s not for the reasons you’d think. Yeah, there are a lot of privacy and liability issues at stake, but putting that aside, it causes us nothing but headaches. For starters, a primary key is supposed to be a unique, non-changing entity. SSN is neither of these. This is particularly true for international students. Many of these students arrive at UMBC without a permanent, government-issued SSN. We issue these students a temporary, bogus SSN, so we can get them into our various systems (SIS, HR, etc). Then, sometime during their stay at UMBC, they get a permanent SSN. And, depending on how the change percolates through our various systems of record, this wreaks unholy havoc on the student’s myUMBC account.

Nothing will illustrate this better than a real-life example. Read on for the gory details.

[More:]

Today I looked at a grad student, who we’ll call Larry (names changed to protect the innocent). When Larry logged into myUMBC, he was only getting the Personal and Support tabs. Well, it turns out that Larry is an international student. He’s also a graduate assistant, which means he has an HR entry as well as a SIS entry. He’s in SIS under his temporary, bogus SSN, and he’s in HR under his real, permanent SSN. As a result, he has two entries in our LDAP directory, one for each data source. When I do an LDAP lookup on his account, it brings up the entry from HR, which is lacking a student affiliation. Thus, Larry doesn’t get any student content in myUMBC.

Now, the first thing to do here is to get Jason to merge the two LDAP entries together. In the meantime, I can grant Larry a temporary student affiliation, which will give him the tabs he needs to see. But, that’s still not enough. SIS still has his old, temporary SSN. When the portal goes to look up Larry’s class schedule, it’s going to use the new, correct SSN, and it’s not going to find any info there. So Larry gets an Academics tab full of blank channels.

The permanent solution here is to get the registrar to update Larry’s SIS records to reflect the new SSN. However, for reasons beyond my comprehension, there always seems to be an interminable amount of time between requesting this and actually seeing the change reflected in SIS. In the meantime, we have to do something so that Larry can access myUMBC. Which brings us to…. the SSN translation table.

For students like this, I have an SIS table (AUXIL.MYUMBC_USER_PREFERENCES) where I store the student’s username, and the student’s SSN as shown in SIS. When the student logs into myUMBC, the portal first checks this table. If it finds an entry matching the student’s username, it uses that SSN to override the one it gets from LDAP. So for Larry, I just plug his bogus SIS SSN into AUXIL.MYUMBC_USER_PREFERENCES, and presto, myUMBC magically starts working for him.

But, we’re still not done. In effect, we’ve created a time bomb. Because eventually, SIS is going to get updated to reflect the student’s real SSN. It could be a week from now, it could be a year from now. But when that happens, the overridden entry will still be out there, and it will continue to map the student to the old SSN. So at some point, Larry’s myUMBC account is going to break again. At that point, I’ll need to delete his entry from AUXIL.MYUMBC_USER_PREFERENCES, and then he’ll finally be fixed for good.

I’ve been dealing with this (ahem) CRAP (I’ll keep this PG-rated) for 6 years now, and once we finally stop using SSNs as primary keys, it’s finally going to end. Students will get an SIS ID, it’ll be unique, it’ll never change, these problems will be gone, and the world will be happier. At least in theory.

Just to document this for future reference.. In uPortal, the AUXIL.MYUMBC_USER_PREFERENCES lookup happens in the UMBC Person Factory (edu.umbc.uportal.UmbcPersonFactory), via the UMBC Local Connection Context (org.jasig.portal.security.UMBCLegacyLocalConnectionContext).

Followup.. in a sudden stroke of brilliance, I added a join against the SIS BADDR.MNAME table to my overridden SSN query. If there’s no BADDR.MNAME data for the SSN, it won’t use it. That way we automatically stop using overridden entries once they become obsolete. That should be a big help.

Quick Bike-to-work Update

Well, here it is May 1 and I’ve biked to work 6 times now (well, 5-1/2 times actually, since I’m at work now and still have to ride home today). The weather has been almost perfect for biking. It’d be nice if it were ever-so-slightly warmer in the mornings, because then I could lose the jacket. But other than that, it’s been hard to complain.

This past weekend I fiddled around a bit with my front derailleur. For more than a year now, it’s had this habit of occasionally dumping the chain when I shift to the smallest chainring. Every time it did it, I swore I was going to adjust it, but I never seemed to get around to it. Anyhow, all I did was tighten the inner limit screw about 1/4 turn, and it seems to have done the trick. Today it was very consistent shifting into the granny. Only thing now, is it seems to “hunt” a bit more when I shift out of the granny into the middle chainring. However, it’s still within the limits of what I’d consider acceptable, so I’m going to leave it like this for the time being. After the season, I’ll take it to the shop for a complete tune-up, and they can worry about it at that point.

Today I did find a good article on derailleur adjustment, so if I’m feeling up to it one day, I might fiddle with it some more.

On another topic, today we found out when our health benefits open enrollment starts at work. So soon, we’ll find out how much more the state is going to spank us for benefits in FY 2007. Cue up the “Imperial Death March” theme now..

Pool coping project looming

Well, May starts tomorrow, and with it comes… the pool project. This is sure to be the topic of many entries over the next couple months.

Background: Late last summer I noticed a loose strip of waterline tile in the deep end of the pool. Further investigation revealed that all of the coping stones in the deep end had also popped loose. Long story short, I planned the repair for this spring. Basic plan is to:

  1. Sawcut the expansion joint (between deck and coping) so the deck doesn’t contact the pool shell;
  2. Rebed the loose coping;
  3. Recaulk the expansion joint.

I’m putting the waterline tile repair off till next year, as it’s mainly cosmetic and I’ve got other stuff to keep me busy this summer..

#1 and #2 are pretty straightforward; for #3, the common practice is to use a self-leveling polyurethane caulk. There’s a pool-specific product called Deck-O-Seal which is commonly used. Of course, being pool specific, it’s pricey. There are other equivalent products sold under different trade names, which are somewhat less expensive if you can find a decent supplier. The brand names I’ve run across include Vulkem, Sonneborn, and Sikaflex. My hope is to find a local supplier for this stuff; that way I avoid paying shipping, and if I need more, I can just run out and get some (possibly multiple times). Anyhow, the great news is, today I found the Sikaflex product at Home Depot in the concrete aisle. Hard to beat Home Depot for convenience.

Now that I have somewhere I can buy the sealant, I can focus on planning the job and getting it done. The plan right now is to start this around mid-May, so I have some time to finish up other projects first. Depending on when we decide to uncover the pool, it may get pushed back… we’ll see.

Alarm Oddity

So, I’ve got the wireless keys programmed into the alarm. Everything seems to work. The only “wild card” here is the range of the things, because the receiver is mounted a little farther away from the garage than I’d like. If the range turns out to be a problem, I’d expect all of the buttons on the keys to work inconsistently. What I’m seeing in practice, is that the garage door button works consistently, but the disarm button is spotty. I get the same behavior with both keys.

I don’t really have an explanation for this, so the first thing I’m going to try is moving the receiver closer to the garage. I’ll mount it in the new spot temporarily, and see how it works (in particular, it needs to still work with my existing wireless zones). The other thing is, I still haven’t installed the status transmitter module. It doesn’t seem like that should have anything to do with it, but I’ll go ahead and install it at the same time, and see how things go.

Stay tuned..

Followup.. turns out the spotty behavior did affect the garage door button after all, so most likely, this was simply an issue of the signals not getting to the receiver. My hypothesis is that the house’s aluminium siding was interfering with signal propagation. The fobs seem much more reliable now that I’ve relocated the receiver.

More on Coppermine

Still playing around with Coppermine, trying to set things up so that Cathy can have a separate login and still have the ability to upload and edit photos in the public albums. First, I tried setting her account up in the registered group. After a bit of fiddling and RTFMing, I was able to get it so that the account could upload to public albums. I had to

  1. Remove the disk quota from the registered group (group admin area, change default quota from 1024K to 0)
  2. Enable registered group to upload to public albums without admin approval (group admin area)
  3. For each album, go to the configuration page (go to album list and click “properties”). In properties, select “Visitors can upload files”

After I did that, I could upload pictures, but once uploaded, I couldn’t do anything further with them (like adding captions etc). So it looks like this isn’t the answer. That leaves me with two options:

  1. Add Cathy’s account to the administrators group; or
  2. Move all the albums to Cathy’s “personal” album space, so she “owns” them; then she should have access to them and I can access them through my administrator account.

For now, I’m going with option #1 because it’s the easiest.

Coppermine

A couple weeks back, I downloaded a PHP/MySQL-based online photo album package called Coppermine. At the time, I was looking for kind of a be-all-end-all-do-everything solution to managing all of our digital photos and publishing them on the web. I installed it and gave it a go last week. Installation was straightforward as soon as I got the MySQL tablespace properly configured. Once it was ready to go, I uploaded some pics to it.

The Coppermine documentation is very much geared towards users with web hosting services, as opposed to people like me who run their own servers. It took me a bit of sifting through directions like “use FTP to upload the pictures to your web hosting service”, before I figured out that all I need to do is place the photos in a directory that my Apache installation can read and write to. Once I did that, I fired up Coppermine’s import tool. And waited. And waited. And waited.

It appears that during the import process, Coppermine runs “convert” (from ImageMagick) on each file to create thumbnails and “intermediate” sized images. From running “top” on my server, it looks like it fires off four “convert” processes at a time (this may be configurable). This process is a bit slow on my crusty old 450mhz server box. So it looks like if I’m going to be importing hundreds of photos, I’m going to need to run this on a machine with a bit more juice. It probably doesn’t help that the web server is currently accessing the photos over an NFS mount.

However, once the import finishes and the photos are online, the viewer works pretty well. I think for now, I’ll scale back my ambitions and just use Coppermine to publish photos I want to share. I’ll move them to a local disk on the web server box, and then I’ll just pick and choose the photos I want to upload to it. I think it’ll do very nicely in that configuration.

More later..

Followup.. Desperately in need of a photo browser for my Linux box, I looked around and found xnview. The Motif interface is a little dated, but it works very nicely and it’s fast. It supposedly also works on Windows and Mac. I played around some more with Coppermine and found that it has a user-level upload tool, where I can upload pictures through the browser. Pretty cool.

Busy yardwork day

I played hooky from work today so I could catch up on some much-needed yardwork. If my work schedule permits, I really like doing that because I can pick a day where the weather is good, knock off all the yardwork, and free up the weekend for more leisurely pursuits. I started at 9:30 this morning doing trimming and edging, then mowed all the grass, then mulched up some twigs with the chipper/shredder. Plus, I relocated one of our compost bins and fixed the door on our big barrel composter. All in all, a very productive day.

Next up, I need to do a little pruning and weeding, and do end-of-season maintenance on the snowblower. Then I’ve got two outside projects I’d like to get done before I have to deal with the pool… a new lid for the sandbox, and a permanent pole for our bird feeder. I hope to get the ball rolling on these this weekend.

Adding content to Perl myUMBC codebase

Urrgh. I added new functionality to the Perl myUMBC codebase today, and I had forgotten what a pain it was. You know things are bad when you wrote the code, and you have to spend an hour trying to recall how it works. Since it looks like the Perl stuff is going to be around for awhile, I figured I might as well document this process while it’s fresh on my mind. Maybe it’ll save me some time down the road.

Just to clarify… when I speak of myUMBC here, I’m just talking about the Perl stuff, not uPortal. With that in mind, here goes.

Background: Everything in myUMBC is database driven. Every link, table, dropdown menu, heading, etc. that you can see, click on, or otherwise manipulate, has a corresponding entry in a database table. All internal URLs in myUMBC are of the form

http://blah.blah/myumbc?function=foo

The function code tells myUMBC what the end user is currently doing. Most of myUMBC’s core functions (registration, etc.) actually have two function codes, one for the initial screen, and one for the results page. Every function code needs to have an entry in the database. Otherwise the user will get a “not authorized” type error. This is to keep users from entering arbitrary function codes and producing undefined results. The database table that contains all of this stuff is called BRCTL.PROD_PROG_DESC (don’t ask about the name).

To add to the confusion, myUMBC also has a built-in function mapping table, which maps shorter function names to possibly-longer Perl subroutine names. For example, the Financial Aid Inquiry function I added today has a short name faidinq which maps to a subroutine finaid_inquiry. There’s no real reason for doing this, other than shortening the URL.

To make a long story short, first, you need a PROD_PROG_DESC entry with PPD_LINK_TYPE set to “function” and PPD_URL set to the name of the Perl subroutine that builds the initial HTML (which could be a table, dropdown etc). Then, you need a second PROD_PROG_DESC entry for the results page. This one should have PPD_URL set to NULL, and PPD_FUNCTION_NAME should match the Perl subroutine that generates the results page.

That’s basically it… unfortunately, that probably didn’t make much sense unless you’re already intimately familiar with the myUMBC Perl codebase. One of these days I’ll improve and expand on this, to make it fit for general consumption. That’s why it’s in my blog and not the Syscore Wiki..

[More:]

6/16: Here’s how I made our new Student Parking Registration form come up:

INSERT INTO prod_prog_desc

    (ppd_prog_id, ppd_url, ppd_desc, ppd_add_date_time,
     ppd_add_user_id, ppd_link_type, ppd_restrict_access,
     ppd_auth_level, ppd_function_name, ppd_portal_disposition)

VALUES

    ('NEWPARK', '%2bParkingRegistrationForm',
     'Student Parking Registration (new)', sysdate, 'paulr',
     'myumbc', 'N', 'password', '+ParkingRegistrationForm', 'maximized')

Great to have notes to refer back to..

Quick note on Palm iCalendar Sync

A couple weeks back, I upgraded my copy of Missing Sync to the latest version, version 5.1.0. Last night I noticed that event deletions from my read-only calendar subscriptions had stopped propagating properly to the Palm. I probably should have suspected something was amiss.. every time I ran a sync, I was getting a sync services dialog telling me that the sync was “changing more than 5% of the calendars on this computer.”

I also had the event deleting problem when I first installed Missing Sync. At the time, the Mark/Space support folks gave me a procedure to erase everything on the Palm, reset the sync history, and sort of “start over”. It worked then, and it worked this time too. I documented the procedure in this post.

Looks like I might want to do this every time I upgrade Missing Sync, just to make sure I’ve got a clean slate and nothing gets wonky.

I’m still happy with Missing Sync. Now I’m pining for a desktop Mac, so I could do a bluetooth sync from anywhere in the house without worrying about firing up the laptop….

Wireless Alarm Keys Demystified

I successfully programmed an Ademco wireless keyfob transmitter today, and figured I’d document the process.. My panel is a Vista-20P and the transmitter is a 5804BD.

  1. Program an RF house ID into the panel. The house ID needs to be a number between 0 and 31. On the Vista-20P, this is done in location *24:

    Enter programming with 4-digit installer code + 800
    Enter *24
    Enter 2-digit house ID
    System chimes to confirm entry

  2. Install batteries in the transmitter. When prying the case open, hold the transmitter with the buttons facing down; otherwise they’ll all fall out when you pull the case apart.
  3. Program the house ID into the transmitter per the instructions. It must match the house ID programmed into the panel.
  4. Program each button individually using zone programming (*56). On the Vista-20P, zones 49 through 64 are reserved for keyfob zones. The following example will program button 4 to disarm the system:

    Enter *56 to enter zone programming
    Enter 1 at Set to Confirm? prompt
    Enter 49 to program zone 49 (or whatever)
    Enter * at summary screen
    At zone type prompt, enter 22 (disarm)
    Enter 1 at partition prompt
    Enter 0000 at report code prompt (no report)
    Input Device type will default to “Button type RF”
    Enter the device serial number at the prompt
    Enter 4 as the loop number (corresponds to button 4)
    Press button 4 on the keyfob at “Xmit to Confirm” prompt
    System confirms that the correct serial number was transmitted
    Review summary screen and press *
    Press 0 at “Program Alpha?” prompt

    Now, exit programming and assign a user number to this button: Enter master code + 8 + user number + #4 + zone number. For user 04 and zone 49, you would enter

    master code + 8 + 04 + # 4 + 49

    Keypad will chime to confirm.

    That’s it; button 4 on the keyfob should now work to disarm the system. The process should be repeated for each button on the fob (each button corresponds to a separate loop number).

Next step is to hook one of the buttons up to the garage door opener. It appears that I need to program the button as zone type 23 (no alarm response), then go into device programming and define an output function to activate the appropriate relay when the zone trips.

This weekend I’ll install the 5800TM transmitter so that the fobs will be able to display system status. I’ll also test the range to see if I’ll need a repeater. Hopefully I won’t.

Followup 4/22… I’ve programmed both keyfobs and everything worked as expected. I’m pretty impressed with the range of these things.. it seems to be pretty close to the advertised 200 feet. It’s looking like I won’t be needing a signal repeater. Haven’t gotten to the 5800TM yet, and may not this weekend, but the fobs don’t need it to work. I’ll use this week to test them out, and assuming they continue to work well, I’ll put the 5800TM in next weekend.