# LEG28032005
# modules/nsperm/init.tcl -
#	Initialization for nsperm module
#

# New approach to the initialization of the nsperm module
# We do not want to reference a file after server startup.
# So all user and group data, hosts allows, denays and permissons go
# into ns_section's.
#
# USERS:
#
# ns_section ns/servers/${server}/modules/nsperm/users
# ns_param user alfred
# ns_param user emma
# ns_param user nobody
#
# ns_section ns/servers/${server}/modules/nsperm/user/alfred
# ns_param name       "Alfred the Great"
# ns_param password   crIh22g3NM6I2
# ns_param allowfrom  127.0.0.1,meine.burg.de
# ns_param denyfrom   0.0.0.0/0.0.0.0
#
# ns_section ns/servers/${server}/modules/nsperm/user/emma
# ns_param password   crhBjmYE7k8JQ
#
# ns_section ns/servers/${server}/modules/nsperm/user/nobody
#
# GROUPS:
#
# ns_section ns/servers/${server}/modules/nsperm/groups
# ns_param group       public
# ns_param group       saints
#
# ns_section ns/servers/${server}/modules/nsperm/group/public
# ns_param member      alfred
# ns_param member      emma
# ns_param member      nobody
#
# ns_section ns/servers/${server}/modules/nsperm/group/saints
# ns_param member      alfred
# ns_param member      emma
#
# PERMISSIONS:
#
# ns_section ns/servers/${server}/modules/nsperm/perms
# ns_param allowuser   alfred:"GET POST":/~alfred*
# ns_param allowgroup  saints:"GET POST MKCOL":/heaven:noinherit
# ns_param denyuser    nobody:"MKCOL PROPATCH MOVE":/private



proc init_nsperm { } {
    
    set config "ns/servers/[ns_info server]/modules/nsperm"

    set default_methods [ns_config $config method \
			     "OPTIONS GET HEAD POST DELETE TRACE PROPFIND PROPPATCH COPY MOVE MKCOL LOCK UNLOCK"]

    # USERS
    set users [ns_configsection $config/users]
    if {$users ne ""} {

	for {set i 0} {$i < [ns_set size $users]} {incr i} {
	    set user [ns_set value $users $i]

	    # compose the basic command to add the user
	    set cmd "ns_perm adduser \"$user\" \
                             \"[ns_config $config/user/${user} password]\" \
                             \"[ns_config $config/user/${user} name]\""

	    set user_config [ns_configsection $config/user/${user}]
	    if {$user_config eq ""} {
		ns_log debug "ns_perm: no config section for user \"$user\"."
	    } else {
		for {set j 0} {$j < [ns_set size $user_config]} {incr j} {
		    switch [ns_set key $user_config $j] {
			allowfrom {
			    append _ns_allow " [ns_set value $user_config $j]"
			}
			denyfrom { 
			    append _ns_deny " [ns_set value $user_config $j]"
			}
		    }
		}
	    }
	    if [info exists _ns_allow] {
		append cmd " -allow $_ns_allow"
		unset _ns_allow
	    }
	    if [info exists _ns_deny] {
		append cmd " -deny $_ns_deny"
		unset _ns_deny
	    }
	    # TODO???: verfiy: at my understanding, the ns_perm command
	    # does not handle several -allow/-deny sections, just one.
	    # but why does it not complain about an invalid hostname?
	    eval $cmd
	    ns_log debug "ns_perm: $cmd"
	}
    }
    
    # GROUPS
    set groups [ns_configsection $config/groups]
    if {$groups ne ""} {
	for {set i 0} {$i < [ns_set size $groups]} {incr i} {
	    set group [ns_set value $groups $i]

	    # compose the basic command to add the user
	    set cmd "ns_perm addgroup $group"
	    
	    set members [ns_configsection $config/group/${group}]
	    if {$members ne ""} {
		for {set j 0} {$j < [ns_set size $members]} {incr j}  {
		    append cmd " \"[ns_set value $members $j]\""
		}
		eval $cmd
		ns_log debug "ns_perm: $cmd"
	    }
	}
    }

    # PERMISSIONS
    set perms [ns_configsection $config/perms]
    if {$perms ne ""} {
	for {set i 0} {$i < [ns_set size $perms]} {incr i} {
	    set action  [ns_set key $perms $i]
	    # user:methods:uri:inhert
	    set args [split [ns_set value $perms $i] :]

	    set user [lindex $args 0]
	    set methods [lindex $args 1]
	    set uri  [lindex $args 2]
	    
	    set cmd "ns_perm $action"
	    if {[lindex $args 3] eq "noinhert"} {
		append cmd " -noinherit"
	    }
	    if {$methods eq ""} { set methods $default_methods }

	    foreach method $methods {
	        eval "$cmd $method $uri \"$user\""
		ns_log debug "ns_perm: $cmd $method $uri \"$user\""
	    }
	}
    }
}


#
# ns_permpasswd lets you set a password in the nsperm passwd file.
# It is implemented in tcl because the passwd file is no inherently a
# part of the nsperm module--just a nice interface provided by the
# supporting Tcl code.
#
# oldpass must either be the user's old password or nsadmin's password
# for the action to succeed.
#

proc ns_permpasswd { targetuser oldpass newpass } {
    ns_log notice "ns_permpassword: obsolete: not updateing passwd file"

    #
    # Verify that this is an allowed action
    #

    if {[catch {ns_perm checkpass $targetuser $oldpass} ignore] != 0} {
	if {[catch {ns_perm checkpass nsadmin $oldpass} ignore] != 0} {
	    return "incorrect old password"
	}
    }

    ns_perm setpass $targetuser [ns_crypt $newpass CU]
    return ""
}


#
# Initialize the module
#

init_nsperm
