// Shows how to add/check/remove permissions for a n entity (resource) of a user or a group entity
func Example_acl() {
	entityManager := initEntityManager()
	fmt.Println("ExampleShowACLAddCheckRemovePermissions")
	fmt.Printf("User %q permission %q is %v\n", userName1, canUsePermission,
		acl.CheckUserPermission(entityManager, userName1, resourceName, en.Permission(canUsePermission)))
	data, _ := entityManager.GetPropertyAttachedToEntity(resourceName, defs.AclPropertyName)
	a, ok := data.(*acl.Acl)
	if ok == false {
		fmt.Println("Error: Cannot get property", defs.AclPropertyName, "attached to resource", resourceName)
		return
	}
	a.AddPermissionToEntity(entityManager, userName1, en.Permission(canUsePermission))
	fmt.Printf("User %q permission %q is: %v\n", userName1, canUsePermission,
		acl.CheckUserPermission(entityManager, userName1, resourceName, en.Permission(canUsePermission)))
	a.AddPermissionToEntity(entityManager, groupName, en.Permission(supportPermission))
	a.AddPermissionToEntity(entityManager, groupName, en.Permission(canUsePermission))
	a.AddPermissionToEntity(entityManager, defs.AclAllEntryName, en.Permission(allPermission))
	a.AddPermissionToEntity(entityManager, userInGroupName1, en.Permission(usersPermission))
	permissions, _ := acl.GetUserPermissions(entityManager, userInGroupName1, resourceName)
	fmt.Printf("All the permissions for user %q on resource %q are: %q\n",
		userInGroupName1, resourceName, permissions)
	permissions, _ = acl.GetUserPermissions(entityManager, groupName, resourceName)
	fmt.Printf("All the permissions for group %q on resource %q are: %q\n", groupName, resourceName, permissions)
	a.RemovePermissionFromEntity(groupName, en.Permission(canUsePermission))
	fmt.Printf("After remove permission: %q from group %q\n", canUsePermission, groupName)
	fmt.Printf("User %q permission %q is: %v\n", userInGroupName1, canUsePermission,
		acl.CheckUserPermission(entityManager, userInGroupName1, resourceName, en.Permission(canUsePermission)))
	fmt.Printf("All the permissions are: %q\n", a.GetAllPermissions())
}
// Add a permission to resource for a given user and verify that it have it
// Remove the permission for the resource from the user and verify it doesn't have it
func Test_addCheckDeletePermission(t *testing.T) {
	initState()
	strFmt := "%v/%v"
	permission := en.Permission(perRead)

	stRestful.UsersList.AddPermission(en.Permission(permission))
	baseURL := fmt.Sprintf(cr.ConvertCommandToRequest(urlCommands[handlePermissionCommand]),
		entityToken, userName1, resourceToken, resourceName1, permissionsToken, permission)
	okURLJ := cr.URL{URL: fmt.Sprintf(strFmt, servicePath, baseURL)}
	url := fmt.Sprintf(strFmt, resourcePath, baseURL)
	exeCommandCheckRes(t, cr.HTTPPutStr, url, http.StatusCreated, "", okURLJ)
	exeCommandCheckRes(t, cr.HTTPGetStr, url, http.StatusOK, "", cr.Match{Match: true, Message: ""})
	exeCommandCheckRes(t, cr.HTTPDeleteStr, url, http.StatusNoContent, "", cr.StringMessage{Str: ""})
	str := fmt.Sprintf("Permission '%v' doesn't allowed", permission)
	exeCommandCheckRes(t, cr.HTTPGetStr, url, http.StatusNotFound, "", cr.Error{Code: 0, Message: str})
}
// Verify that if a user was a member of a group in an ACL of entity with a permission
// If the group was removed, the user doesn't have the permission
// than the permission was added to the user, the user have the permission
// and than the user was removed from the list and readded (maybe its another user), it doesn't have the permission
func Test_CheckPermissionWhenUserIsRemovedAndAdded(t *testing.T) {
	el := initEntityManager()
	a := NewACL()
	p := en.Permission(PerRead)
	// create entity list with disk, user, group entities (user1 is part of group)
	// set ACL to disk, add the group aclAclEntry with read permission to disk ACL
	el.AddUser(userName)
	el.AddGroup(groupName)
	el.AddUserToGroup(groupName, userName)
	el.AddPropertyToEntity(resourceName, defs.AclPropertyName, a)
	Entry, _ := NewEntry(groupName)
	a.addAclEntry(Entry)
	Entry.AddPermission(p)
	if CheckUserPermission(el, userName, resourceName, p) != true {
		t.Errorf("Test fail: '%v' permission must be set, %v", p, a)
	}
	el.RemoveGroup(groupName)
	if CheckUserPermission(el, userName, resourceName, p) == true {
		t.Errorf("Test fail: '%v' permission must not be allowed, %v", p, a)
	}
	Entry, _ = NewEntry(userName)
	a.addAclEntry(Entry)
	Entry.AddPermission(p)
	if CheckUserPermission(el, userName, resourceName, p) != true {
		t.Errorf("Test fail: '%v' permission must be set, %v", p, a)
	}
	el.RemoveUser(userName)
	el.AddUser(userName)
	if CheckUserPermission(el, userName, resourceName, p) == true {
		t.Errorf("Test fail: '%v' permission must not be allowed, %v", p, a)
	}
}
// Verify that a nil groups list returns no permissions
// Verify that permission can't be added to a nil groups list
// Verify that permission can't be added to an undefined group
// Verify that removal of a user from a group removes that user's permissions
func Test_GroupListCorrectness(t *testing.T) {
	el := initEntityManager()
	a := NewACL()

	el.AddPropertyToEntity(resourceName, defs.AclPropertyName, a)
	if CheckUserPermission(el, userName, resourceName, PerRead) == true {
		t.Error("Test fail: Have permissions for empty lists")
	}
	el.AddPermission(en.Permission(PerRead))
	err := a.AddPermissionToEntity(el, groupName, PerRead)
	if err == nil {
		t.Error("Test fail: Set permissions for a group but the group list is nil", a)
	}
	err = a.AddPermissionToEntity(el, groupName, PerRead)
	if err == nil {
		t.Error("Test fail: Set permissions for an unknown group", groupName, a)
	}
	el.AddGroup(groupName)
	el.AddUser(userName)
	el.AddUserToGroup(groupName, userName)
	e, _ := NewEntry(groupName)
	a.addAclEntry(e)
	a.AddPermissionToEntity(el, groupName, PerRead)
	if CheckUserPermission(el, userName, resourceName, PerRead) != true {
		t.Errorf("Test fail: '%v' permission must be set, %v", PerRead, a)
	}
	el.RemoveUserFromGroup(groupName, userName)
	if CheckUserPermission(el, userName, resourceName, PerRead) == true {
		t.Errorf("Test fail: user: %v doesn't have permission '%v', %v", userName, PerRead, a)
	}
}
func (en *EnRestful) restRemovePermission(request *restful.Request, response *restful.Response) {
	id := request.PathParameter(permissionIDParam)
	err := en.st.UsersList.RemovePermission(ent.Permission(id))
	if err != nil {
		en.setError(response, http.StatusNotFound, err)
	} else {
		response.WriteHeader(http.StatusNoContent)
	}
}
func (en *EnRestful) restCreatePermission(request *restful.Request, response *restful.Response) {
	id := request.PathParameter(permissionIDParam)
	err := en.st.UsersList.AddPermission(ent.Permission(id))
	if err != nil {
		en.setError(response, http.StatusPreconditionFailed, err)
		return
	}
	response.WriteHeaderAndEntity(http.StatusCreated, en.getPermissionURLPath(request, id))
}
func generateAcl() (string, *acl.Acl, error) {
	stRestful.UsersList.AddResource(resourceName1)
	stRestful.UsersList.AddGroup(groupName)
	for _, name := range usersName {
		stRestful.UsersList.AddUser(name)
		stRestful.UsersList.AddUserToGroup(groupName, name)
	}
	aclData := acl.NewACL()
	for _, name := range usersName {
		for _, p := range usersPermissions {
			stRestful.UsersList.AddPermission(en.Permission(p))
			aclData.AddPermissionToEntity(stRestful.UsersList, name, en.Permission(p))
		}
	}
	stRestful.UsersList.AddPermission(en.Permission(perAll))
	aclData.AddPermissionToEntity(stRestful.UsersList, defs.AclAllEntryName, perAll)
	stRestful.UsersList.AddPropertyToEntity(resourceName1, defs.AclPropertyName, aclData)
	data, _ := json.Marshal(aclData)
	return string(data), aclData, nil
}
func generateAcl(el *en.EntityManager) bool {
	for n := range el.Resources {
		tmpE, _ := el.GetPropertyAttachedToEntity(n, defs.AclPropertyName)
		a, ok := tmpE.(*Acl)
		if ok == false {
			return false
		}
		for name := range el.Users {
			a.AddPermissionToEntity(el, name, en.Permission("uP"+n))
		}
	}
	return true
}
func (a AclRestful) restDeletePermission(request *restful.Request, response *restful.Response) {
	aclData, aclInfo, err := a.getResourceAclData(request, response)
	if err != nil {
		a.setError(response, http.StatusNotFound, err)
		return
	}
	err = aclData.RemovePermissionFromEntity(aclInfo.UserName, en.Permission(aclInfo.Permission))
	if err != nil {
		a.setError(response, http.StatusNotFound, err)
	} else {
		response.WriteHeader(http.StatusNoContent)
	}
}
// Verify that if a permission set to the All ACL list it is valid for all users
func Test_AllListPermissions(t *testing.T) {
	el := initEntityManager()
	a := NewACL()
	el.AddUser(userName)
	el.AddPropertyToEntity(resourceName, defs.AclPropertyName, a)
	el.AddPermission(en.Permission(PerRead))
	a.AddPermissionToEntity(el, defs.AclAllEntryName, PerRead)
	if CheckUserPermission(el, userName, resourceName, PerRead) != true {
		t.Errorf("Test fail: '%v' permission must be set, %v", PerRead, a)
	}
	if CheckUserPermission(el, userName, resourceName, PerWrite) == true {
		t.Errorf("Test fail: '%v' permission must be clear, %v", PerWrite, a)
	}
}
// THe same test as Test_Permissions, but in this test, the permissions are updated by
// calling AddPermission/RemovePermission with the aclAclEntry name/type and the updated permissions
func Test_UpdatePermissions(t *testing.T) {
	el, a, usersName, setEntries, resetEntries, expectUserPermissions, expectGroupPermissions, _ := setupCheckPermissions(false)

	for _, v := range setEntries {
		for _, p := range v.permissions {
			el.AddPermission(en.Permission(p))
			a.AddPermissionToEntity(el, v.name, p)
		}
	}

	for i, v := range resetEntries {
		for _, p := range v.permissions {
			a.RemovePermissionFromEntity(v.name, p)
		}
		for _, name := range usersName {
			checkExp(t, el, a, i, name, expectUserPermissions[i])
			checkExp(t, el, a, i, name, expectGroupPermissions[i])
		}
	}
}
func (a AclRestful) restSetPermission(request *restful.Request, response *restful.Response) {
	a1, aclInfo, err := a.getResourceAclData(request, response)
	if err != nil {
		a.setError(response, http.StatusNotFound, err)
		return
	}
	if a1 == nil {
		eAcl := acl.NewACL()
		a.addAclToResource(request, response, aclInfo.ResourceName, eAcl)
		a1, aclInfo, err = a.getResourceAclData(request, response)
		if err != nil {
			a.setError(response, http.StatusInternalServerError, err)
			return
		}
	}
	err = a1.AddPermissionToEntity(a.st.UsersList, aclInfo.UserName, en.Permission(aclInfo.Permission))
	if err != nil {
		a.setError(response, http.StatusNotFound, err)
	} else {
		response.WriteHeaderAndEntity(http.StatusCreated, a.getURLPath(request, entityToken, fmt.Sprintf("%v/%v/%v/%v/%v", aclInfo.UserName, resourceToken, aclInfo.ResourceName, permissionsToken, aclInfo.Permission)))
	}
}
// Verify that empty permission can't be added
// verify that valid permission can be added
// verify that permission that is in the list can't be added again
// verify that only permission that are in the list can be removed
// Verify that at the end of the loop, no permissions are left in the list
func Test_AddRemovePermissions(t *testing.T) {
	expected := []bool{true, false}
	name := "User1"

	a, _ := NewEntry(name)
	// verify that empty permission can't be added
	p := en.Permission("")
	_, err := a.AddPermission(p)
	if err == nil {
		t.Errorf("Test fail: Invalid permission: '%v' was added to the %v", p, a)
	}
	// verify that valid permission can be added
	// verify that permission that is in the list can't be added again
	for _, exp := range expected {
		ok, permission := addPermissions(a, permissionsMap, exp)
		if ok == false {
			if exp == true {
				t.Errorf("Test fail: Fail to add valid permission: '%v' to %v", permission, a)
			} else {
				t.Errorf("Test fail: Permission: '%v' was added to %v but is was already added before", permission, a)
			}
		}
	}

	// verify that only permission that are in the list can be removed
	for p, val := range permissionsMap {
		err := a.RemovePermission(p)
		if err != nil && val == true {
			t.Errorf("Test fail: Fail to remove valid permission: '%v' from %v", p, a)
		} else if err == nil && val == false {
			t.Errorf("Test fail: Permission: '%v' was removed from %v, but it wasn't in the permissions list", p, a)
		}
	}
	if len(a.Permissions) != 0 {
		t.Error("Test fail: The permission list of", a, "must be empty")
	}
}
func (a AclRestful) restCheckPermission(request *restful.Request, response *restful.Response) {
	a1, aclInfo, err := a.getResourceAclData(request, response)
	if err != nil {
		a.setError(response, http.StatusNotFound, err)
		return
	}
	if a1 == nil {
		a.setError(response, http.StatusNotFound, err)
		return
	}
	ok := false
	status := http.StatusOK
	if a1 != nil && aclInfo != nil {
		ok = acl.CheckUserPermission(a.st.UsersList, aclInfo.UserName, aclInfo.ResourceName, en.Permission(aclInfo.Permission))
	}
	str := fmt.Sprintf("Permission '%v' is allowed", aclInfo.Permission)
	if ok == false {
		str = fmt.Sprintf("Permission '%v' doesn't allowed", aclInfo.Permission)
		status = http.StatusNotFound
	}
	res := cr.Match{Match: ok, Message: str}
	response.WriteHeaderAndEntity(status, res)
}