mirror of https://github.com/mikkolehtisalo/iw.git
246 lines
7.1 KiB
Go
246 lines
7.1 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
"github.com/revel/revel"
|
|
"github.com/twinj/uuid"
|
|
"github.com/mikkolehtisalo/revel/ldapuserdetails"
|
|
"github.com/mikkolehtisalo/revel/acl"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type Activity struct {
|
|
Activity_id string
|
|
Timestamp time.Time
|
|
User_id string
|
|
User_name string
|
|
Activity_type string
|
|
Target_type string
|
|
Target_title string
|
|
Target_id string
|
|
MatchedPermissions []string
|
|
// For the "flattened" acls...
|
|
Readacl string
|
|
Writeacl string
|
|
Adminacl string
|
|
}
|
|
|
|
// Oldest: 1 month
|
|
func GetActivities() []Activity {
|
|
revel.TRACE.Printf("GetActivities()")
|
|
activities := []Activity{}
|
|
db := get_db()
|
|
defer db.Close()
|
|
|
|
err := db.Select(&activities, "select * from activities where timestamp > now() - interval '1 month' order by timestamp desc")
|
|
|
|
if err != nil {
|
|
revel.ERROR.Printf("GetActivities() err: %+v", err)
|
|
}
|
|
|
|
revel.TRACE.Printf("GetActivities() returning: %+v", activities)
|
|
return activities
|
|
}
|
|
|
|
func GetActivity(activity_id string) Activity {
|
|
revel.TRACE.Printf("GetActivity() id: %+v", activity_id)
|
|
activities := []Activity{}
|
|
activity := Activity{}
|
|
db := get_db()
|
|
defer db.Close()
|
|
|
|
err := db.Select(&activities, "select * from activities where activity_id=uuid_in($1)", activity_id)
|
|
|
|
if err != nil {
|
|
revel.ERROR.Printf("Unable to get activity %+v: %+v", activity_id, err)
|
|
}
|
|
|
|
if len(activities) > 0 {
|
|
activity = activities[0]
|
|
}
|
|
|
|
revel.TRACE.Printf("GetActivity() returning: %+v", activity)
|
|
|
|
return activity
|
|
}
|
|
|
|
// Is there a similar activity within one minute range?
|
|
func ActivityExists(a Activity) bool {
|
|
exists := false
|
|
|
|
activities := []Activity{}
|
|
db := get_db()
|
|
defer db.Close()
|
|
|
|
err := db.Select(&activities, "select * from activities where $1 - timestamp < interval '1 minute' and user_id=$2 and activity_type=$3 and target_type=$4 and target_id=$5",
|
|
a.Timestamp, a.User_id, a.Activity_type, a.Target_type, a.Target_id)
|
|
|
|
if err != nil {
|
|
revel.ERROR.Printf("ActivityExists() err: %+v", err)
|
|
}
|
|
|
|
if len(activities) > 0 {
|
|
exists = true
|
|
}
|
|
|
|
|
|
return exists
|
|
}
|
|
|
|
// Flatten the inherited ACL structure, for performance reasons
|
|
// If the ACLs of the parent items are edited, the ACLs of activity will not change..
|
|
func update_acl(a *Activity) {
|
|
filterable := acl.Get_filterable([]Activity{*a})
|
|
acls := acl.GetACLEntry("activity:" + a.Activity_id, filterable[0], true)
|
|
|
|
// Remove the duplicates from previous (it will generate them) and flatten the result
|
|
var read, write, admin []string
|
|
for _, item := range acls.ACLs {
|
|
if item.Permission == "read" && item.Principal != "" {
|
|
read = append(read, item.Principal)
|
|
}
|
|
if item.Permission == "write" && item.Principal != "" {
|
|
write = append(write, item.Principal)
|
|
}
|
|
if item.Permission == "admin" && item.Principal != "" {
|
|
admin = append(admin, item.Principal)
|
|
}
|
|
}
|
|
|
|
a.Readacl = strings.Join(read, ",")
|
|
a.Writeacl = strings.Join(write, ",")
|
|
a.Adminacl = strings.Join(admin, ",")
|
|
}
|
|
|
|
// Flattens the ACL before saving
|
|
func (a *Activity) Save() {
|
|
revel.TRACE.Printf("Activity Save(): %+v", a)
|
|
|
|
db := get_db()
|
|
defer db.Close()
|
|
|
|
update_acl(a)
|
|
|
|
_, err := db.Exec("insert into activities(activity_id, timestamp, user_id, user_name, activity_type, target_type, target_title, target_id, readacl, writeacl, adminacl) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
|
|
a.Activity_id, a.Timestamp, a.User_id, a.User_name, a.Activity_type, a.Target_type, a.Target_title, a.Target_id, a.Readacl, a.Writeacl, a.Adminacl)
|
|
|
|
if err != nil {
|
|
revel.ERROR.Printf("Activity Save(): error %+v", err)
|
|
}
|
|
|
|
}
|
|
|
|
func SaveActivity(target interface{}) {
|
|
revel.TRACE.Printf("target: %+v", target)
|
|
a := Activity{}
|
|
a.Activity_id = uuid.NewV4().String()
|
|
|
|
switch target.(type) {
|
|
case *Wiki:
|
|
w := target.(*Wiki)
|
|
a.Timestamp = w.Modified
|
|
a.User_id = w.Create_user
|
|
dets := ldapuserdetails.Get_user_details(w.Create_user)
|
|
a.User_name = dets.Visiblename
|
|
a.Activity_type = w.Status
|
|
a.Target_type = "WIKI"
|
|
a.Target_title = w.Title
|
|
a.Target_id = w.Wiki_id
|
|
if !ActivityExists(a) {
|
|
a.Save()
|
|
}
|
|
case *Page:
|
|
p := target.(*Page)
|
|
a.Timestamp = p.Modified
|
|
a.User_id = p.Create_user
|
|
dets := ldapuserdetails.Get_user_details(p.Create_user)
|
|
a.User_name = dets.Visiblename
|
|
a.Activity_type = p.Status
|
|
a.Target_type = "PAGE"
|
|
a.Target_title = p.Title
|
|
|
|
// We have to save the parent node for treeStore, or "" if it's on first level....
|
|
parent := ""
|
|
if p.Depth > 0 {
|
|
split := strings.Split(p.Path, "/")
|
|
parent = split[len(split)-2]
|
|
}
|
|
a.Target_id = p.Wiki_id + "/" +parent + "/" + p.Page_id
|
|
|
|
if !ActivityExists(a) {
|
|
a.Save()
|
|
}
|
|
case *Attachment:
|
|
x := target.(*Attachment)
|
|
a.Timestamp = x.Modified
|
|
a.User_id = x.Create_user
|
|
dets := ldapuserdetails.Get_user_details(x.Create_user)
|
|
a.User_name = dets.Visiblename
|
|
a.Activity_type = x.Status
|
|
a.Target_type = "ATTACHMENT"
|
|
a.Target_title = x.Filename
|
|
a.Target_id = x.Wiki_id + "/" + x.Attachment_id
|
|
if !ActivityExists(a) {
|
|
a.Save()
|
|
}
|
|
}
|
|
}
|
|
|
|
// ACL stuff
|
|
|
|
// Never inherit the parent!
|
|
func (a Activity) BuildACLInheritation() bool {
|
|
return true
|
|
}
|
|
|
|
// Activity + activity_id
|
|
func (a Activity) BuildACLReference() string {
|
|
return "activity:" + a.Activity_id
|
|
}
|
|
|
|
// No parent..
|
|
func (a Activity) BuildACLParent() string {
|
|
return strings.ToLower(a.Target_type) + ":" + a.Target_id
|
|
}
|
|
|
|
// Set the matched permissions to a variable
|
|
func (a Activity) SetMatched(permissions []string) interface{} {
|
|
a.MatchedPermissions = permissions
|
|
return a
|
|
}
|
|
|
|
func (a Activity) BuildACLEntry(reference string) acl.ACLEntry {
|
|
revel.TRACE.Printf("BuildACLEntry() %+v", reference)
|
|
var entry acl.ACLEntry
|
|
|
|
if reference != ("activity:"+a.Activity_id) {
|
|
|
|
if strings.Index(reference, "page") == 0 {
|
|
// We are not working on this copy, get from database
|
|
re := regexp.MustCompile("page:([^/]*)/([^/]*)/(.*)")
|
|
m := re.FindStringSubmatch(reference)
|
|
wref := m[1]
|
|
pref := m[3]
|
|
pa := GetPage(wref, pref)
|
|
entry = entry_helper(pa.Readacl, pa.Writeacl, pa.Adminacl, reference, pa)
|
|
}
|
|
|
|
if strings.Index(reference, "wiki") == 0 {
|
|
// This must be wiki!
|
|
re := regexp.MustCompile("wiki:(.*)")
|
|
ref := re.FindStringSubmatch(reference)[1]
|
|
wi := GetWiki(ref)
|
|
entry = entry_helper(wi.Readacl, wi.Writeacl, wi.Adminacl, reference, wi)
|
|
}
|
|
|
|
} else {
|
|
// It's exactly the originating item!
|
|
entry = entry_helper(a.Readacl, a.Writeacl, a.Adminacl, reference, a)
|
|
}
|
|
|
|
revel.TRACE.Printf("BuildACLEntry() returning %+v", entry)
|
|
|
|
return entry
|
|
}
|