Details
-
Type: Bug
-
Status: Resolved
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 2.0.6, 2.1
-
Fix Version/s: 2.1.1
-
Component/s: None
-
Labels:None
-
Environment:Confluence 3.1, Database Name: PostgreSQL, Database Version: 8.3.8, Application Server: Apache Tomcat/5.5.20, Custom Space User Management Plugin: 2.0.6
-
Internal Complexity:Unknown
-
Internal Value:Unknown
-
Rank:Issue can not be ranked.
Description
Customer is listed as a Space Admin for a space in Confleunce. They go to Browse-Manage Users/Groups and select the group they want to add a new user to. They click on Submit and receive an error message saying, "User was not removed from the group (possibly it was not a member)". Only Confluence admins can add users. All our Space Admins are reporting the same problem.
Attachments
-
- Confluence Error with Groups.doc
- 19/Nov/10 8:00 AM
- 120 kB
- Debbie Boerke
-
- csum_debug_log.log
- 25/Jan/11 12:20 PM
- 38 kB
- Lucas Croce
-
$i18n.getText("admin.common.words.hide")
- permissionmgmt-2.1.0-SNAPSHOT.jar
- 07/Feb/11 1:37 PM
- 555 kB
- Gary S. Weaver
-
- META-INF/MANIFEST.MF 0.1 kB
- atlassian-plugin-min.xml 0.0 kB
- atlassian-plugin.xml 8 kB
- csum/.../AbstractPagerPaginationSupportCachingSpaceAction.class 12 kB
- csum/.../AtlassianPlugin-min.properties 0.0 kB
- csum/.../AtlassianPlugin.properties 17 kB
- csum/.../AtlassianPlugin_de-min.properties 0.0 kB
- csum/.../AtlassianPlugin_de.properties 19 kB
- csum/.../AtlassianPlugin_en-min.properties 0.0 kB
- csum/.../AtlassianPlugin_en.properties 17 kB
- csum/confluence/.../CacheConstants.class 0.8 kB
- csum/.../BaseCustomPermissionConfigAction.class 6 kB
- csum/.../CsumConfigValidationResponse.class 1 kB
- csum/.../CustomPermissionConfigAction.class 8 kB
- csum/.../CustomPermissionConfigConstants.class 4 kB
- csum/.../CustomPermissionConfigurable.class 2 kB
- csum/.../CustomPermissionConfiguration.class 18 kB
- csum/.../LegacyConfigConstants.class 1 kB
- csum/.../LegacyConfigurationMigrator.class 3 kB
- csum/.../CustomPermissionConstants.class 0.5 kB
- csum/.../CustomPermissionManagerAction.class 41 kB
- csum/.../CustomPermissionManagerActionContext.class 3 kB
- csum/.../CustomPermissionServiceManager.class 4 kB
- csum/confluence/.../AddException.class 0.8 kB
- csum/confluence/.../FindException.class 0.8 kB
- csum/confluence/.../RemoveException.class 0.8 kB
- csum/.../ServiceAuthenticationException.class 0.9 kB
- csum/confluence/.../ServiceException.class 2 kB
- csum/.../UsersNotFoundException.class 0.9 kB
- csum/.../GroupManagementService.class 0.9 kB
$i18n.getText("admin.common.words.show")- permissionmgmt-2.1.0-SNAPSHOT.jar
- 07/Feb/11 1:37 PM
- 555 kB
- Gary S. Weaver
-
$i18n.getText("admin.common.words.hide")
- permissionmgmt-2.1.0-SNAPSHOT.obr
- 07/Feb/11 1:37 PM
- 529 kB
- Gary S. Weaver
-
- META-INF/MANIFEST.MF 0.1 kB
- obr.xml 0.6 kB
- permissionmgmt-2.1.0-SNAPSHOT.jar 555 kB
$i18n.getText("admin.common.words.show")- permissionmgmt-2.1.0-SNAPSHOT.obr
- 07/Feb/11 1:37 PM
- 529 kB
- Gary S. Weaver
-
$i18n.getText("admin.common.words.hide")
- permissionmgmt-2.1.1-SNAPSHOT.jar
- 08/Feb/11 1:26 PM
- 554 kB
- Gary S. Weaver
-
- META-INF/MANIFEST.MF 0.1 kB
- atlassian-plugin-min.xml 0.0 kB
- atlassian-plugin.xml 8 kB
- csum/.../AbstractPagerPaginationSupportCachingSpaceAction.class 12 kB
- csum/.../AtlassianPlugin-min.properties 0.0 kB
- csum/.../AtlassianPlugin.properties 17 kB
- csum/.../AtlassianPlugin_de-min.properties 0.0 kB
- csum/.../AtlassianPlugin_de.properties 19 kB
- csum/.../AtlassianPlugin_en-min.properties 0.0 kB
- csum/.../AtlassianPlugin_en.properties 17 kB
- csum/confluence/.../CacheConstants.class 0.8 kB
- csum/.../BaseCustomPermissionConfigAction.class 6 kB
- csum/.../CsumConfigValidationResponse.class 1 kB
- csum/.../CustomPermissionConfigAction.class 8 kB
- csum/.../CustomPermissionConfigConstants.class 4 kB
- csum/.../CustomPermissionConfigurable.class 2 kB
- csum/.../CustomPermissionConfiguration.class 18 kB
- csum/.../LegacyConfigConstants.class 1 kB
- csum/.../LegacyConfigurationMigrator.class 3 kB
- csum/.../CustomPermissionConstants.class 0.5 kB
- csum/.../CustomPermissionManagerAction.class 41 kB
- csum/.../CustomPermissionManagerActionContext.class 3 kB
- csum/.../CustomPermissionServiceManager.class 4 kB
- csum/confluence/.../AddException.class 0.8 kB
- csum/confluence/.../FindException.class 0.8 kB
- csum/confluence/.../RemoveException.class 0.8 kB
- csum/.../ServiceAuthenticationException.class 0.9 kB
- csum/confluence/.../ServiceException.class 2 kB
- csum/.../UsersNotFoundException.class 0.9 kB
- csum/.../GroupManagementService.class 0.9 kB
$i18n.getText("admin.common.words.show")- permissionmgmt-2.1.1-SNAPSHOT.jar
- 08/Feb/11 1:26 PM
- 554 kB
- Gary S. Weaver
-
- wikicsum.txt
- 10/Dec/10 2:20 PM
- 66 kB
- Joel Daves
Activity
In addition, please provide info on how the repository is setup and your configuration settings (we don't need to know the specifics that you may not want publicized such as group prefix, etc., we just want to know whether you are using LDAP, Jira, or whatever for your user repo).
We're also seeing this issue since updating to 2.0.6. Haven't tried rolling back to 2.0.5 yet since there seem to be problems with plugin downloads today from Atlassian's site.
I'm attaching a debug log from reproducing the issue on my test server. We aren't using LDAP, but we do use an external mechanism for user authentication (users are still stored in the confluence db, has no impact on groups). In this instance, user spaceadmin (admin permissions on space testspace) is trying to remove testuser from the testspace-group-test. The wiki admin user can add or remove group members, but the space admin always gets an "User xxxxx was not removed from group wyyyyyy (possibly it was not a member)" error on adds or removes of users. The space admin can add empty groups, but gets the same error when attempting to create a group and add users at the same time. The space admin also cannot delete groups, returning a "doesn't have rights to delete group" error.
Other information of note: Confluence 3.4.3, Apache Tomcat 6.0.29, MySQL 5.1.41, Java 1.6.0_22
Debug log from space admin's attempt to remove a user from a group managed via CSUM.
Gary - We are having the same problem.
Everything was working just fine with version 2.0.6 of the plugin and Confluence 3.0.1
We recently upgraded to Confluence 3.4.3 and now our space administrators are no longer able to maintain their groups. They can not add or remove users. We missed this issue during our testing because all of the testers are Confluence Administrators.
I can add some log information if needed.
I just wanted to add that we tried rolling our development environment back to version 2.0.5 of the plugin. The same problem exists with that version as well.
Wanted to add that we are also experiencing this problem in Confluence 3.4.5 with version 2.0.6 of the plugin. Tried downgrading to 2.0.5 and that does not resolve the issue.
Gary - As this problem has been open for close to two months, I was just wondering if you had any updates?
Our users are getting rather frustrated and our support team receives numerous requests to update groups weekly. At this point we are considering engaging an Atlassian partner (Appfire or Adaptavist) to have them correct the issue.
I know you're busy with your day job and other personal responsibilities, I was just hoping you could provide some sort of update.
Thanks, John
John,
I'm sorry. I will see what I can do. While any of the other contracted dev teams are welcome to work on CSUM to enhance it, I'm sure everyone would rather save their money if they are able.
Gary
Reproduced locally with current CSUM trunk build in vanilla Confluence 3.4.6 standalone.
If I am in confluence-administrators, I am able to add and remove groups and users using the plugin.
If I am only a space administrator, I get the erroneous error message when attempting to add user admin to new group (test-)mynewgroup in the test space in CSUM:
"The following error(s) occurred:
- User admin was not removed from group test-mynewgroup (possibly it was not a member)
"
So, the good news is that I can reproduce it. The bad news is that I don't have a solution yet.
I tried changing a few security settings in Confluence, but it seemed to have no effect.
So here is my plan of action:
- Will explore the API, similar user administration plugins, and related documentation to see if something was changed that is easy enough to fix.
- If nothing found, will create a simple plugin/macro that attempts to manage group membership and if it fails also, create a Jira ticket with Atlassian and attach that project to it to help them understand what we are trying to do and how we can do it in newer versions. I'm a little surprised that they didn't notice this before now. My guess is that it is because admins (not space admins) were testing it out.
- While waiting on that, if there is no other solution, might look into other Confluence APIs (maybe it would let us use the API given an admin's username and password to manage the users). That would be the last-ditch attempt, because I'd rather people not have to configure a system user, as that might not be an option in every environment.
Thanks for your patience,
Gary
- User admin was not removed from group test-mynewgroup (possibly it was not a member)
- Will explore the API, similar user administration plugins, and related documentation to see if something was changed that is easy enough to fix.
- If nothing found, will create a simple plugin/macro that attempts to manage group membership and if it fails also, create a Jira ticket with Atlassian and attach that project to it to help them understand what we are trying to do and how we can do it in newer versions. I'm a little surprised that they didn't notice this before now. My guess is that it is because admins (not space admins) were testing it out.
- While waiting on that, if there is no other solution, might look into other Confluence APIs (maybe it would let us use the API given an admin's username and password to manage the users). That would be the last-ditch attempt, because I'd rather people not have to configure a system user, as that might not be an option in every environment.
Working with Ben Speakmon of Atlassian in http://jira.atlassian.com/browse/DEVNET-939
Ben Speakmon [Atlassian] added a comment - 13/Jan/11 5:31 PM
As far as I can tell, the change was made in 2.10 to restrict group membership to server admins, not space admins. That being said, you can get the relevant user management objects directly and allow your users to manage groups while skipping the security check. I've done this myself in a JIRA plugin.Of course, you'll have to be extra careful that you don't open up any other holes, warn your users, etc., etc., but I think you can rescue this.
Cheers,
Ben
Was not able to find the plugin he was talking about, so provided him a list of most of the parts of the API we use for user/group management, told him how we access it, and asked him what we should be using instead.
Ben Speakmon [Atlassian] added a comment - 13/Jan/11 5:31 PM As far as I can tell, the change was made in 2.10 to restrict group membership to server admins, not space admins. That being said, you can get the relevant user management objects directly and allow your users to manage groups while skipping the security check. I've done this myself in a JIRA plugin. Of course, you'll have to be extra careful that you don't open up any other holes, warn your users, etc., etc., but I think you can rescue this. Cheers, BenWas not able to find the plugin he was talking about, so provided him a list of most of the parts of the API we use for user/group management, told him how we access it, and asked him what we should be using instead.
Wanted to add another finding here. We have 2 instances of Confluence running. One is on a hosted environment and the other is not hosted. The hosted environment has this bug but not the environment that is not hosted. It works fine in the not hosted environment. The hosted environment worked at one time. We made no changes to the system and it just stopped working. After we found that it broke, we upgraded the CSUM Plugin to 2.0.6 and tested again. It was still broke. We moved it back to 2.0.5 but it still won't work.
Debbie,
Thanks for the info.
From what Ben Speakmon of Atlassian said (although I haven't confirmed it yet), Confluence 2.10 and later do not support managing group membership by a space administrator. By this I don't mean just that the plugin doesn't let you- I mean that the Atlassian Confluence API doesn't let you- at least, not in the way that it did before (and I don't know the "new" way yet that Ben alluded to).
If the version of Confluence is less than 2.10, the problem we are talking about should not occur. In versions of Confluence 2.10 or greater, if the user is a confluence administrator, they will not see the issue, but if they are only a space administrator, they would see the issue.
I've only confirmed this in Confluence 3.4.6 (current version). I've not tried to reproduce in other versions.
If you are sure that what I'm saying is incorrect please let me know, as it will help expedite a possible remedy.
If Ben doesn't come up with a solution, it could mean that we would need to modify the CSUM plugin to use an alternative Confluence API (remote or SOAP), assuming they allow us to do what we need to. And if that doesn't work- who knows. Maybe we'd have to modify the DB directly, but we'd run into all sorts of complexity if we went down that path.
The current workaround is (and I don't think this is feasible for most people) to give confluence administrator rights to the space admins or revert to Confluence 2.9.x (which is almost certainly not feasible for most people unless they can just delay/abandon their Confluence upgrade from pre-2.10).
We'll keep working on it, and please keep providing as much info as you can that you think will help.
Gary
Gary,
In our non-hosting instance of Confluence, we just upgrading to version 3.3.3 from version 3.0.2 and it worked before the upgrade and still working after the upgrade. (I just asked a space admin, who is not a Confluence admin, to update a group list today and it worked.) On our hosted instance of Confluence we are running version 3.1. It used to work running this version. We made absolutely no changes and it stopped working.
Debbie,
Are you absolutely sure that the space admin whom it is working for is not in the confluence-administrators group?
Could you look specifically at their user and give me the list of all permissions they have both in the space admin area and in the confluence admin area? (You don't have to give me names of business-specific groups- I just want to have this information to pass to Atlassian to help us diagnose the issue.)
Since this could be session-specific, please also have that person completely close their browser and re-login if you do take their confluence-administrator rights away from them.
Also, if you could have that user (if you are sure that they are only the space admin) try to create a brand new group containing administrative users that they have never added to a group before using the left side of the Manage Users/Groups tab that would be best, because that is how I replicated the issue (e.g. in the left side create new group "superheroes" and under that specify one of the confluence administrators' usernames).
I'm in the dark otherwise at why one of your Confluence 3.1 instances works and the other one stopped working all of a sudden, so if the other idea doesn't work out, I would need you to provide the differences in configuration between working and non-working 3.1 instances (and I understand that it was working and it stopped, but I have no other way to help debug it other than trying to determine the difference between working and non-working).
Thanks in advance,
Gary
Gary,
I'm a 100% sure these users are space admins only. I'm one of the people who maintains the confluence administrators group. So, I'm 100% sure these users where never on that group list. In fact, one of the individuals, I created her user account so I'm sure that person was never on the administrator group.
In the permissions page, I have all the boxes checked for that individual. I verified this user by looking at the account in Confluence Admin and the group list for confluence adminstrators is not listed.
They had tried on muliple days to do this so I'm pretty sure they had restarted their PC between times. But, will verify on Monday. Also, on Monday, I will have one of them create a group like you asked and post my findings.
We only have one instance of Confluence running 3.1. The other one that is working is now running 3.3.3 (upgraded from version 3.0.2). The main difference (besides version) is the 3.1 is on a host environment and the 3.3.3 is not hosted.
Debbie,
So to lay it out, here are the facts, as we know them:
- Ben of Atlassian claims Confluence 2.10+ may contain this "feature", which is causing the issue in CSUM.
- Confluence 3.1 (hosted), 3.4.3, 3.4.5, and 3.4.6 are showing this issue
- Confluence 3.3.3 is not showing this issue
That wouldn't appear to make sense at first unless the security feature was implemented in Confluence (2.10?, 3.1), then removed (not shown in 3.3.3), then implemented again (3.4.3, 3.4.5, 3.4.6). Or, possibly the issue is with Confluence 3.4.x and the hosted instance is lying about the version because it contains later Confluence API classes/jars (this would be interesting, but unlikely). And there are other potential reasons (like someone made a mistake or fed you bad info, or someone made an assumption, etc.).
If someone had time to try to add a new group with user in CSUM as space admin in various vanilla versions of Confluence and provide that feedback here, maybe we could track down when this issue occurred. I've only personally confirmed it in 3.4.6.
For now, let's see what the Atlassian developer than Ben forwarded this issue to says.
Let us know what happens from your user testing on Monday.
Thanks for your patience,
Gary
- Ben of Atlassian claims Confluence 2.10+ may contain this "feature", which is causing the issue in CSUM.
- Confluence 3.1 (hosted), 3.4.3, 3.4.5, and 3.4.6 are showing this issue
- Confluence 3.3.3 is not showing this issue
Hello Gary, Debbie,
We have also used the plugin without any trouble on a confluence 3.1.1 instance. Space Admins who were not part of the confluence administrators (nor in the past) were able to add groups, add users to groups and removed users from groups.
Now we have upgraded to 3.4.3 and we experience the same issues as you mention.
In our structure the Space Admins really need to be able to add users and groups themselves without the support of confluence administrators so the fact that this plugin is not working anymore is a major for us.
Look forward to all ideas or work arounds that you would know.
Thanks,
Geert Peter de Oude
OnyxVirtualAcademy.com
Gary,
We were using Confluence 3.1.2 with the plugin fine until we upgraded to 3.4.5. I don't recall exactly which version it was. Could it be related to the new security features that Atlassian implemented in Confluence 3.3 for confluence-administrators? (That being that admins have to login to confluence in addition to logging into the admin interface for "sudo" rights).
Gary,
As a test, I created a user account and used my computer to test. (Users who reported this problem were unavailable to test this morning.) I rebooted my PC and deleted temp files, etc from my browser. Then logged in as this test user, I signed onto Confluence and went to a space I was given Admin rights to. I created a group list and it created fine, then I tried to add a user, received the error message. Also tried to create a group and add a user at the same time, group would not create at all using that method and received the same error message.
One thing I noticed is the error message has changed since November when I first reported the problem. The error message use to read:
User username was not removed from group groupname (possibly it was not a member)
Now the error message reads:
User groupname was not removed from group username (possbily it was not a member)
(Yes, I have screen shots to proof this error message changed.)
Debbie,
Will take a look. Thanks!
Geert Peter de Oude and Lucas Croce, thank you for your information! It helps.
Gary
Also, got info from Matt Ryall of Atlassian:
Matt Ryall [Atlassian] added a comment - 16/Jan/11 4:50 PM
Hi Gary,The UserAccessor in Confluence fits into our service layer, meaning it is responsible for permission checks as well as performing the actual changes. I'm not sure about Confluence 3.1 or 3.4, but some permission checking has been in place in UserAccessor.addMembership() since Confluence 2.7. In that release, we added a new layer of administrative permission and it was necessary to ensure the UserAccessor checked the group membership of the person doing the change before acting on it.
To do user management changes without permission checks in all Confluence versions up to 3.4.x, you can use the Atlassian-User managers directly: com.atlassian.user.GroupManager and com.atlassian.user.UserManager. Note that these methods will not fire events or perform other Confleunce-specific functionality which the UserAccessor normally takes care of.
From Confluence 3.5, there will be a new low-level API for user management that will be documented when we release it. The interface is called CrowdService.
Regards,
Matt
So, will try to switch it over to UserManager ( http://docs.atlassian.com/atlassian-user/2006-10-11/com/atlassian/user/UserManager.html ) and GroupManager ( http://docs.atlassian.com/atlassian-user/2006-10-11/com/atlassian/user/GroupManager.html ) and post a build back on this ticket for testing.
Might also try to make it work at least partially with Confluence 3.5-m1 ( http://docs.atlassian.com/crowd/current/com/atlassian/crowd/embedded/api/CrowdService.html and http://confluence.atlassian.com/display/EMBCWD/Home ). I won't have LDAP working in that yet, but while I'm in the code, I may as well.
Best Regards,
Gary
Matt Ryall [Atlassian] added a comment - 16/Jan/11 4:50 PM Hi Gary, The UserAccessor in Confluence fits into our service layer, meaning it is responsible for permission checks as well as performing the actual changes. I'm not sure about Confluence 3.1 or 3.4, but some permission checking has been in place in UserAccessor.addMembership() since Confluence 2.7. In that release, we added a new layer of administrative permission and it was necessary to ensure the UserAccessor checked the group membership of the person doing the change before acting on it. To do user management changes without permission checks in all Confluence versions up to 3.4.x, you can use the Atlassian-User managers directly: com.atlassian.user.GroupManager and com.atlassian.user.UserManager. Note that these methods will not fire events or perform other Confleunce-specific functionality which the UserAccessor normally takes care of. From Confluence 3.5, there will be a new low-level API for user management that will be documented when we release it. The interface is called CrowdService. Regards, MattSo, will try to switch it over to UserManager ( http://docs.atlassian.com/atlassian-user/2006-10-11/com/atlassian/user/UserManager.html ) and GroupManager ( http://docs.atlassian.com/atlassian-user/2006-10-11/com/atlassian/user/GroupManager.html ) and post a build back on this ticket for testing. Might also try to make it work at least partially with Confluence 3.5-m1 ( http://docs.atlassian.com/crowd/current/com/atlassian/crowd/embedded/api/CrowdService.html and http://confluence.atlassian.com/display/EMBCWD/Home ). I won't have LDAP working in that yet, but while I'm in the code, I may as well. Best Regards, Gary
Attached untested build which now uses UserManager and GroupManager for everything except advanced and partial username queries, which I didn't see right away the equivalent in newer Confluence APIs.
In theory (although untested), this should work in Confluence 2.10-3.4.x. I have not yet integrated with CrowdService so that it would work with Confluence 3.5.x+.
Please test it out if you can and let me know whether it works. Be sure to test as both an admin and a space administrator. Please also ensure the finding users by partial username and advanced user queries work, as it is possible that they don't.
(Note: same fix with add_16.gif image missing fix build now in SUSR-123.)
I've installed the test build in our test instance of confluence and it crashed. I'll post the the stack trace below:
Cause:
java.lang.IllegalArgumentException: Method 'doDefault()' is not defined in action 'class csum.confluence.permissionmgmt.config.CustomPermissionConfigAction'
at com.opensymphony.xwork.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:305)
Stack Trace:
java.lang.IllegalArgumentException: Method 'doDefault()' is not defined in action 'class csum.confluence.permissionmgmt.config.CustomPermissionConfigAction'
at com.opensymphony.xwork.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:305)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:170)
at com.opensymphony.xwork.interceptor.AroundInterceptor.intercept(AroundInterceptor.java:35)
at com.opensymphony.xwork.DefaultActionInvocation.invoke(DefaultActionInvocation.java:165)
at .............
Lucas,
Thanks. Looks like that a similar issue is noted here, but I don't see any other mention of it:
http://jira.atlassian.com/browse/CONF-15011
It is actually lying, because it is defined. Currently it is:
public String doDefault() throws Exception { log.debug("CustomPermissionConfigAction - Inside doDefault .."); LegacyConfigurationMigrator.migrateLegacyConfiguration(bandanaManager); configureFormValuesWithPersistedConfig(); fixFormValues(); // NOTE: the main reason for doing this and showing errors even though it might be your first time to the page // is that people that have already configured the plugin once before will expect errors to show up on the page // when they visit it, even if they didn't post to it yet. if (!validateConfiguration()) { return ERROR; } return super.doDefault(); }
And super should end up calling:
http://docs.atlassian.com/confluence/latest/com/atlassian/confluence/core/ConfluenceActionSupport.html#doDefault%28%29
Per the issue I noted, it would appear that maybe the plugin couldn't be instantiated, and this is a misleading error.
Could you check the log again for the part of the log when you attempted to install the plugin and check to see if anything else is in there, and if not, perhaps turn on full debug logging (because unfortunately, I don't know the package that would be relevant). Ensure that any logs you submit are scrubbed of private data (as there may be more of a risk of giving info away with full root level debugging on).
Thanks in advance,
Gary
public String doDefault() throws Exception { log.debug("CustomPermissionConfigAction - Inside doDefault .."); LegacyConfigurationMigrator.migrateLegacyConfiguration(bandanaManager); configureFormValuesWithPersistedConfig(); fixFormValues(); // NOTE: the main reason for doing this and showing errors even though it might be your first time to the page // is that people that have already configured the plugin once before will expect errors to show up on the page // when they visit it, even if they didn't post to it yet. if (!validateConfiguration()) { return ERROR; } return super.doDefault(); }
I found the following information in the log when I reinstalled the plugin while running a "tail -f atlassian-confluence.log". Hope this helps.
2011-01-24 16:40:22,397 ERROR pool-7-thread-1 atlassian.plugin.manager.DefaultPluginManager enableConfiguredPluginModule There was an error loading the descriptor 'confluenceGroupManagementService' of plugin 'raju.kadam.confluence.permissionmgmt'. Disabling.
– referer: https://confluence-url/plugins/servlet/upm | url: /wiki/rest/plugins/1.0/ | userName: ******
com.atlassian.plugin.PluginParseException: java.lang.ClassCastException: $Proxy29 cannot be cast to com.atlassian.user.UserManager
at com.atlassian.plugin.module.LegacyModuleFactory.getModuleClass(LegacyModuleFactory.java:58)
at com.atlassian.plugin.descriptors.AbstractModuleDescriptor.loadClass(AbstractModuleDescriptor.java:176)
at com.atlassian.plugin.descriptors.AbstractModuleDescriptor.enabled(AbstractModuleDescriptor.java:423)
at com.atlassian.confluence.plugin.descriptor.ComponentModuleDescriptor.enabled(ComponentModuleDescriptor.java:50)
at com.atlassian.plugin.manager.DefaultPluginManager.notifyModuleEnabled(DefaultPluginManager.java:1416)
at com.atlassian.confluence.plugin.ConfluencePluginManager.notifyModuleEnabled(ConfluencePluginManager.java:123)
at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModule(DefaultPluginManager.java:1227)
at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModules(DefaultPluginManager.java:1194)
at com.atlassian.plugin.manager.DefaultPluginManager.addPlugins(DefaultPluginManager.java:690)
at com.atlassian.plugin.manager.DefaultPluginManager.scanForNewPlugins(DefaultPluginManager.java:428)
at com.atlassian.plugin.manager.DefaultPluginManager.installPlugins(DefaultPluginManager.java:331)
at sun.reflect.GeneratedMethodAccessor793.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy9.installPlugins(Unknown Source)
at com.atlassian.confluence.plugin.EventDispatchingPluginController.installPlugins(EventDispatchingPluginController.java:85)
at sun.reflect.GeneratedMethodAccessor793.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy11.installPlugins(Unknown Source)
at sun.reflect.GeneratedMethodAccessor793.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.atlassian.plugin.osgi.hostcomponents.impl.DefaultComponentRegistrar$ContextClassLoaderSettingInvocationHandler.invoke(DefaultComponentRegistrar.java:129)
at $Proxy141.installPlugins(Unknown Source)
at sun.reflect.GeneratedMethodAccessor793.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy352.installPlugins(Unknown Source)
at com.atlassian.upm.PluginAccessorAndControllerImpl$1.doInTransaction(PluginAccessorAndControllerImpl.java:84)
at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:25)
at com.atlassian.sal.spring.component.SpringHostContextAccessor$1.doInTransaction(SpringHostContextAccessor.java:88)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
at com.atlassian.sal.spring.component.SpringHostContextAccessor.doInTransaction(SpringHostContextAccessor.java:82)
at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.atlassian.plugin.osgi.hostcomponents.impl.DefaultComponentRegistrar$ContextClassLoaderSettingInvocationHandler.invoke(DefaultComponentRegistrar.java:129)
at $Proxy189.doInTransaction(Unknown Source)
at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:154)
at $Proxy189.doInTransaction(Unknown Source)
at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:21)
at sun.reflect.GeneratedMethodAccessor743.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56)
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy381.execute(Unknown Source)
at com.atlassian.upm.PluginAccessorAndControllerImpl.installPlugin(PluginAccessorAndControllerImpl.java:65)
at com.atlassian.upm.impl.PluginArtifactInstallHandler.installPlugin(PluginArtifactInstallHandler.java:30)
at com.atlassian.upm.PluginInstaller.execute(PluginInstaller.java:120)
at com.atlassian.upm.PluginInstaller.install(PluginInstaller.java:79)
at com.atlassian.upm.rest.resources.install.InstallFromFileTask.executeTask(InstallFromFileTask.java:32)
at com.atlassian.upm.rest.resources.install.InstallTask.call(InstallTask.java:29)
at com.atlassian.upm.rest.resources.install.InstallTask.call(InstallTask.java:14)
at com.atlassian.upm.rest.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:63)
at com.atlassian.upm.rest.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:57)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassCastException: $Proxy29 cannot be cast to com.atlassian.user.UserManager
at csum.confluence.permissionmgmt.service.impl.BaseGroupManagementService.<init>(BaseGroupManagementService.java:80)
at csum.confluence.permissionmgmt.service.impl.ConfluenceGroupManagementService.<init>(ConfluenceGroupManagementService.java:61)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at com.atlassian.plugin.module.LegacyModuleFactory.getModuleClass(LegacyModuleFactory.java:35)
... 106 more
Updated plugin to use current supported Atlassian SDK and attached permission-management-2.1.0-SNAPSHOT.jar and USR/trunk/target/permission-management-2.1.0-SNAPSHOT.obr.
Does this help at all? Probably not, but please let me know if it does.
Thanks in advance,
Gary
Am fairly sure this is due to using ContainerManager to attempt to get at UserManager, etc. = pains from moving to Atlassian Plugins v1 to v2. Going to set it up to autowire these...
Removed calls to ContainerManager so that hopefully will be set via setter injection (will worry about moving to construction injection later). I think this is the nail in the coffin of pre-Confluence 2.10 support. Could have kept trying to go with Atlassian plugins v1, but throwing everything at it currently...
Attached new build. Please test it out and let me know if this fixes things. Sorry for all of the trouble in having to test. Wish I could help more with that, but am slammed at work.
Note: if permission-management-2.1.0-SNAPSHOT.jar doesn't work, try permission-management-2.1.0-SNAPSHOT.obr.
Gary
No longer crashing but doesn't see any of the existing groups. Message is "There are currently no groups with rights to view space SPACEKEY and matching the group name pattern SPACEKEY-* defined for this space in the plugin configuration." Double checked the plugin config to make sure that it is set properly and as far as I can tell, it is.
Adding new ones returns a "All groups added successfully" message but nothing actually happens. I've never heard of an .obr file. Is that something I need for this to work?
Lucas,
Sorry- nevermind about the obr file. (It is an OSGi repository file, but it isn't needed, but I wasn't sure since we just switched to Atlassian Plugins v2.)
Please turn on debug logging for the plugin if you don't mind and attach the log file after you've edited it to remove all private information. (See Troubleshooting section here: https://studio.plugins.atlassian.com/wiki/display/SUSR/Confluence+Space+User+Management+Plugin and also turn on Confluence user API debug logging here: http://confluence.atlassian.com/display/DOC/Requesting+External+User+Management+Support first.)
Thanks,
Gary
Attaching the contents of the log during testing. I've removed the rest of the log as it is rather large. There were three primary error messages.
Attaching latest build that uses constructor injection. Has not been tested.
That build seems to be working. I'll have one of my space admins test it and post the results.
Just received word from a space admin that the plugin does not appear to be working for him. Same problem as the original.
Ok, if I had time, I would just try it out. If you have time, if you could set yourself (assuming there is another admin to fix afterwards) as a space admin to replicate the process so that you can:
- Identify what things don't work
- Provide specific bits of logs along with a description of the action you were trying to indicate what didn't work
Just providing one of these partial, scrubbed logs at a time would help most.
If you don't have time, I totally understand.
There may be additional calls that I can switch to using managers for (that supposedly don't do auth checks). But I was doing global search/replace/fix and the only remaining calls that may be denied that I couldn't switch that I know of are the calls to userAccessor to do queries/search, but not for the normal listing of users.
Thanks again. If you don't have time, let me know, and it will just have to wait until I get more time. Really apprecaite all of your help.
Gary
- Identify what things don't work
- Provide specific bits of logs along with a description of the action you were trying to indicate what didn't work
Unfortunately, I don't have the time to do in-depth testing. If any of the other users of this plugin want to step in here, go right ahead.
Understood. Will take a look as soon as I can (may be a few days or more). I apologize in advance for the delay.
fixed locally, tested with confluence 3.4.6 successfully. fixing a css resource issue and will post shortly.
Attaching latest build with fix for delete group issue and fix for issue with resources (js and css) not loading in later versions of Confluence. I'm pretty sure that all of this breaks compatibility with older versions of Confluence, but I don't know how far back yet without more testing. I tested against Confluence 3.4.6 because that is what I had installed.
Let me know if this works for you and if so, I'll release it.
Thanks Garry,
I have installed the latest fix and it seems to work just fine.
We run Confluence 3.4.6.
We will ask some Space Admins to test this as well.
Thanks a lot for your efforts. Highly appreciated (especially by our Space Admins who will love this progress).
Marking as fixed and released as v2.1.0 so I could get this out quickly, because I tested as space admin in Confluence 3.4.6 successfully. Please open a new ticket if you find anything wrong with v2.1.0. Thanks so much for your patience and help.
My test users are reporting an inability to delete groups. The log snippet is:
2011-02-08 14:18:44,279 ERROR ajp-8009-4 permissionmgmt.service.impl.ConfluenceGroupManagementService removeGroup_Confluence2_6_0Compatible User 'rake.t2' doesn't have rights to delete group 'demospace-janworkshop'
– url: /customspacemgmt/permissions/docustompermissionsmanage.action | userName: rake.t2 | action: docustompermissionsmanage
2011-02-08 14:18:44,286 ERROR ajp-8009-4 csum.confluence.permissionmgmt.CustomPermissionManagerAction errorWithRemoteUserInfo Service exception (logged in user=rake.t2,VS<EMAIL_ADDRESS>– url: /customspacemgmt/permissions/docustompermissionsmanage.action | userName: rake.t2 | action: docustompermissionsmanage
csum.confluence.permissionmgmt.service.exception.RemoveException: User 'rake.t2' doesn't have rights to delete group 'demospace-janworkshop'
at csum.confluence.permissionmgmt.service.impl.ConfluenceGroupManagementService.removeGroup_Confluence2_6_0Compatible(ConfluenceGroupManagementService.java:265)
at csum.confluence.permissionmgmt.service.impl.ConfluenceGroupManagementService.removeGroups(ConfluenceGroupManagementService.java:164)
at csum.confluence.permissionmgmt.CustomPermissionManagerAction.manage(CustomPermissionManagerAction.java:959)
at csum.confluence.permissionmgmt.CustomPermissionManagerAction.execute(CustomPermissionManagerAction.java:720)
I'll confirm and then reopen if need be.
I'm reopening; I can reproduce my user's report that 2.1.0 doesn't appear to allow for group deletion. Adding works, and the user mgmt side appears fixed though. I'm on 3.4.6, by the way.
Scott,
I will verify again that I can delete a group created by a space admin in Confluence 3.4.6 with CSUM v2.1.0 and will post back in a minute. I tested it out in 2.10, 3.2, and 3.4.6 so I'm really surprised and wondering if there is something about your environment different than vanilla confluence that is causing the problem. (I know that you use the Confluence Shibboleth Plugin, but am assuming just using Confluence as the user repo. Not sure what would be different than vanilla Confluence that would make a difference.)
Something that I'm afraid of (I'm really hoping this is not the case) is that in the process of updating to Atlassian Plugins v2, the configuration has gotten messed up (using the wrong key), but I don't have an instance handy to test that since I just use the vanilla Confluence for testing with a fresh DB. Could you check to ensure your old configuration is still there in the plugin?
Could you also possibly:
- Turn on debug logging in atlassian-user and csum as mentioned in the plugin wiki page under troubleshooting.
- Have the space admin try again and post the scrubbed debug log to this ticket.
If you can't have them do that, then if you could:
- Turn on debug logging in atlassian-user and csum as mentioned in the plugin wiki page under troubleshooting.
- Add yourself as a space admin to a space (with full permissions via Space Admin tab).
- Remove yourself from confluence-administrators.
- Logout and log back in (probably not necessary, but just in-case).
- Add a new group to the space.
- Either start tailing the log or echo > into it to clear. (confluence_home/logs/...)
- Delete the group and if it fails scrub the log and attach to this ticket.
- Get an admin to add you back to confluence-administators group.
Thanks,
Gary
- Turn on debug logging in atlassian-user and csum as mentioned in the plugin wiki page under troubleshooting.
- Have the space admin try again and post the scrubbed debug log to this ticket.
- Turn on debug logging in atlassian-user and csum as mentioned in the plugin wiki page under troubleshooting.
- Add yourself as a space admin to a space (with full permissions via Space Admin tab).
- Remove yourself from confluence-administrators.
- Logout and log back in (probably not necessary, but just in-case).
- Add a new group to the space.
- Either start tailing the log or echo > into it to clear. (confluence_home/logs/...)
- Delete the group and if it fails scrub the log and attach to this ticket.
- Get an admin to add you back to confluence-administators group.
I double-checked the config and the option for group management is still on, and I was able to add a group with a non-admin user. Then deleting the same group I just added didn't work.
Last time I tried to get DEBUG for specific categories to work, it didn't, and I had to turn on DEBUG for the entire wiki, which took hours to scrub and didn't reveal anything terribly useful, so somebody else will probably need to manage that. If you can't reproduce, just close again and I'll work this from my end.
Was able to reproduce delete group issue in CSUM 2.1.0 in Confluence 3.4.6. I must have only tested group deletion in the other versions of Confluence, even though I could have sworn I tested it also in 3.4.6. Since I can reproduce though, at least have something to work with. (Argh.)
Will remove Confluence 3.4.x compatibility for now until I get this working this afternoon.
Attaching permissionmgmt-2.1.1-SNAPSHOT.jar with fix. Testing...
Tested group delete in Confluence 3.4.6 with 2.1.1-SNAPSHOT and works, so releasing...
Gary - Just wanted to let you know that we have done some simple testing on our Confluence 3.4.3 installation and everything appears to be working. I'll let you know if we find anything out of the ordinary.
Thanks for all the hard work on this one. I really appreciate it. - John
If the user is not a member of the confluence-administrators group this updated plugin does not work for Confluence 3.3.3
Debbie,
Thanks for letting us know. Could you do two things for me to help us fix this?
1. Send us debug logs that you've removed any non-public data from manually as described in under Troubleshooting in the CSUM wiki page. (Try to do this in a test server where you clear the logs (echo > (logfilename)) just before doing the operation that is causing trouble and copy that log right afterwards, scrub private data from it manually, and attach it to this ticket if it is safe for public consumption.)
2. While waiting on us to fix, try the previous version, 2.0.5: https://studio.plugins.atlassian.com/wiki/display/SUSR/Confluence+Space+User+Management+Plugin
We introduced some user and Atlassian requested additional error messages and read-only checking in 2.0.6, but it seems to be problematic in instances that use LDAP (one of the purposes of 2.0.6 was to keep space admins from thinking that they could manage read-only groups), and perhaps in other environments as well.
Thanks,
Gary


I have more than 10 years of experience as a system administrator, Windows/Linux.
I love Ruby on Rails Framework web development.
Developing skills towards CI/CD, Jenkins, Terraform, GitHub, GitLub, Heroku.
Computer skills:
Office programs, DOS, Windows, 9x, NT, 2000, Windows XP. 7. Vista8. 10. Windows Server Administration 2003, 2008, 2012. Active Directory. DNS, DHCP, VPN, RDP.
Integration, test, installs, configure and advance troubleshooting network applications, systems data analysis.
Writing technical documentations. Configuration local printers, print-servers. WI-FI, network security.Unix. Linux Debian, Ubuntu. bash. Email client: Exim, Procmail. PfSense. Squid. Apache. Computer Networking. Routing MikroTik, CISCO, ASUS, TP-Link.
System administrator, leaning towards culture of DevOps.
Administration of servers, workstations, computer systems and network equipment.
Installation of operating systems(desktop-server) Windows, Linux, FreeBSD. Server setup. Windows 2003. 2008. 2012 AD. GPO. RDP. Configuring Routers, gateway. FreeBSD. CISCO. Mikrotik. TP-Link. ASUS. e.t.c WI-FI Access points. Setup of personal computers, operating systems Windows XP, 7. Vista 8. 10.
UNIX: FreeBSD. (as a gateway) pf. pfSense. Email clients: EXIM. Postfix Linux: Ubuntu 14.04 LTS/16.04.5 LTS. Debian GNU Linux. Install Apache, NGINX, Configuration. Squid, Zabbix, bash, scripts, ssh.
Configuration Gateways / Routers: Mikrotik, CISCO, D-link, ASUS, network equipment. Connecting offices, setting up VPN, RDP, MPD5, for remote connection to the central office. Installation LAN. SCS. Purchase of PC and network equipment. Block repair of the PC, Servers. Support 1C service, Me-Doc, Client's of Bank, Liga Zakon.Skills of working with Amazon AWS WEB services ES2. Security Group. IAM. S3. Route 53. VPC. NAT Gateway. Elastic LB. Application LB. Lambda
Mastering DevOps culture. CI/CD, Git, GitHub, GitLab, Jenkins, Docker, Ansible, Puppet
Installation of operating systems (desktop-server) Windows, Linux. Server setup. Windows 2008. 2012. RDP. OpenVPN Configuring Routers, CISCO, Mikrotik, TP-Link, ASUS. WI-FI Access points. Setup of personal computers, VMware, operating systems Windows 10. Ubuntu 16.04, 18.04. CentOS7 Support and consultation of users a local network. Service of printing and copying equipment. Network-Printers. Support Client's of Bank.
Installation of operating systems (desktop-server) Windows, Linux, FreeBSD. Server setup. Windows 2003. 2008. 2012. AD, GPO, RDP. Configuring Routers, gateway. FreeBSD, CISCO, Mikrotik, TP-Link, ASUS. WI-FI Access points. Setup of personal computers, operating systems Windows XP, 7. Vista 8. 10. Support and consultation of users a local network, remote offices (GAS Station, Tank farm, Carpool). Service of printing and copying equipment. Printers, Print-Server. Support 1C service, Me-Doc, Client's of Bank, Liga Zakon. Video surveillance, video recorders Dahua.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003. 2008. DNS, AD, GPO, RDP, VPN. Configuring Routers, gateway. FreeBSD. CISCO. Mikrotik. TP-Link. ASUS. Setup of personal computers, operating systems Windows XP. 7. Vista8. Support and consultation of users a local network, remote offices. Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon. Working with other FreeBSD operating systems as a server system, Open VPN, MPD5, Postfix.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003. 2008. DNS, AD, GPO, RDP, VPN. Configuring Routers, gateway. FreeBSD. CISCO. Mikrotik. TP-Link. ASUS. Setup of personal computers, operating systems Windows XP. 7. Vista 8. Support and consultation of users a local network, remote offices Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon. Working with other FreeBSD operating systems as a server system, Open VPN, MPD5, Postfix.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003. 2008. DNS, AD, GPO, RDP, VPN. Configuring Routers, gateway. FreeBSD. CISCO. Mikrotik. TP-Link. ASUS. Setup of personal computers, operating systems Windows XP, 7, 8. Support and consultation of users a local network, remote offices Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon. Working with other FreeBSD operating systems as a server system, Open VPN, MPD5, Postfix.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003. 2008. DNS, AD, GPO, RDP, VPN. Configuring Routers, gateway. FreeBSD, CISCO, Mikrotik TP-Link, ASUS. Setup of personal computers, operating systems Windows XP, 7, 8. Support and consultation of users a local network, remote offices Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon. Working with other FreeBSD operating systems as a server system, Open VPN, MPD5, Postfix.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003. 2008. DNS, AD, GPO, RDP, VPN, MSSQL 2005. Configuring Routers, gateway. FreeBSD. Setup of personal computers, operating systems, MS Windows XP. 7. Vista 8. Support and consultation of users a local network, accounting financial department. Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon. Working with other FreeBSD operating systems as a server system, Open VPN, MPD5, Postfix.
Installation of operating systems MS Windows, FreeBSD. Server setup. Windows 2003, DNS, AD, GPO, RDP, VPN. Linux Debian. Configuring Routers, gateway, FreeBSD. VPN, MPD5, Postfix. Setup of personal computers, operating systems, MS Windows XP, 7. Support and consultation of users of a local network, accounting financial department. Antivirus protection. Purchase of computer equipment, components, network equipment. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon.
Installation of operating systems MS Windows. Server setup. Windows 2003, DNS. AD. GPO. WSUS. Configuring Routers, gateway, FreeBSD. Linux. Setup of personal computers, operating systems, MS Windows XP. 7. Support and consultation of users a local network. Antivirus protection. Service of printing and copying equipment. Printers, Print-Server. Administration, maintenance, backup, update, Me-Doc, Client's of Bank, Liga Zakon.
I`m interested in Ruby. Web-development Ruby on Rails framework. GitHub. Docker. SQLite. Apart from being a newbie web developer, I enjoy most of my time being outdoors. In the summer I like to walk in the woods. I enjoy biking, and windsurfing/boardsailing.
When forced indoors, I participate in many different webinars, conferences to keep abreast of new products in the IT industry. I follow a number of sci-fi and fantasy genre movies. I spend a large amount of my free time exploring the latest technology advancements in the front-end web development world, and DevOps.


Sliders, les mondes parallèles ;-)
In this project, I used both HTML, CSS and javascript. The javascript section was focused on building motion between image files.
NGUYEN Thoai My - Images sliding
In this project, I used both HTML, CSS and javascript. The javascript section was focused on building motion between image files.


An error has occured
We are experiencing technical problems and are unable to process your application for an emergency travel document. If you don't receive an email from us, unfortunately any data you've entered might be lost.
If you require urgent assistance, please contact your nearest consulate so that we can help with your enquiry.


Boost your chances to
Land that dream job
Start by doing what's necessary, then what's possible, and suddenly you are doing the impossible. Let’s help you start the impossible
Start by doing what's necessary, then what's possible, and suddenly you are doing the impossible. Let’s help you start the impossible
Harness an array of professionally designed and carefully selected templates to help you land that dream job
See TemplateThis helps you kickstart your access to a whole new experience of seemless and easy to use cv creation and editing tool.
Gives you a range of customisable template options to select from.
Avails you with the experience of our cv builder. customise your cv on the go.
After customising, you get an option to either download or share cv directly with the recruiter.


:: com :: sun :: star :: deployment ::
|
| unpublished |
exception DependencyException |
|
|
- Base Hierarchy
DependencyException
┗ ::com::sun::star::uno::Exception
|
- Usage Restrictions
- not published
- Description
- describes unsatisfied dependencies a deployment unit has on its target
environment.
This exception is intended to be used with an
::com::sun::star::task::XInteractionHandler.
- Since
- OOo 2.0.4
|
| Elements' Details |
UnsatisfiedDependencies
sequence< ::com::sun::star::xml::dom::XElement > UnsatisfiedDependencies;
- Description
- a sequence of dependencies represented by XML elements.
The exact nature of those XML elements is deliberately left open, so
that new kinds of dependencies can be defined in the future.
OOo 2.0.4 does not define any kinds of dependencies. Each such XML
element should have an attribute whose global name consists of the
namespace name
http://openoffice.org/extensions/description/2006 and the
local part name and whose value is a human-readable
(english) description of the dependency. If an instance of OOo does not
know more about a specific kind of dependency, it should display the
value of that attribute to the user.
The sequence must not be emtpy, and none of the elements may be
NULL.
|
|
Top of Page
Copyright © 2013, The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache, the Apache feather logo, Apache OpenOffice and OpenOffice.org are trademarks of The Apache Software Foundation. Other names may be trademarks of their respective owners.


National Assembly has no power to enact law on hate speech for states – Falana
by The Eagle OnlineA Human Rights Lawyer, Femi Falana, says that the National Assembly has no power to enact a law on hate speech for the entire country.
Falana said this while discussing as a panelist at Digital Voting Summit organised by RestoreNaija, an NGO, on Monday in Abuja.
He said that such law was not with the purview of the NASS but the state.
The Senior Advocate of Nigeria (SAN) said that while the issue of hate speech fell under residual list, the National Assembly was empowered to legislate on exclusive and concurrent lists.
“Under Section 4 of the Constitution, NASS can only legislative on matters in the exclusive and concurrent lists.
“I have looked at those lists, I have not found anyway where the NASS has been empowered to make the law on hate speech. It is a state affair on residual list.
“Let everybody know his or her limitations of power so that we will not make mistake.
“If you want to proscribe death penalty, you can do so in your state. In Lagos State for instance, the execution of death penalty has been declared illegal by a court in Lagos.
“Whether you want to kill someone by hanging or firing squad, the court in Lagos has said that it is against Section 34 that has abolished any form of torture.”
According to him, if any state wants to legislate on hate speech, it can do so it within its jurisdiction.
Falana said that the Cybercrime Act had taken care of the entire fiats regarding hate speech by making stringent conditions, including fine and prison terms for offenders.
Previous Post
First trauma conference holds in Lagos
Next Post
9th House working to meet parliamentary staff demands — Gbajabiamila


Open source, interactive data science and scientific computing across over 40 programming languages.
The Jupyter Notebook is a web application that allows you to create and share documents that contain live code, equations, visualizations and explanatory text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, machine learning and much more.
The Notebook has support for over 40 programming languages, including those popular in Data Science such as Python, R, Julia and Scala.
Leverage big data tools, such as Apache Spark, from Python, R and Scala. Explore that same data with pandas, scikit-learn, ggplot2, dplyr, etc.
JupyterHub is a multiuser version of the notebook designed for centralized deployments in companies, university classrooms and research labs.
Manage users and authentication with PAM, OAuth or integrate with your own directory service system. Collaborate with others through the Linux permission model.
Deploy the Jupyter Notebook to all users in your organization on centralized servers on- or off-site.
Use Docker containers to scale your deployment and isolate user processes using a growing ecosystem of prebuilt Docker containers.
Deploy the Notebook next to your data to provide unified software management and data access within your organization.
The Jupyter Notebook is based on a set of open standards for interactive computing. Think HTML and CSS for interactive computing on the web. These open standards can be leveraged by third party developers to build customized applications with embedded interactive computing.
Jupyter Notebooks are an open document format based on JSON. They contain a complete record of the user's sessions and embed code, narrative text, equations and rich output.
Go backThe Notebook communicates with computational Kernels using the Interactive Computing Protocol, an open network protocol based on JSON data over ZMQ and WebSockets.
Go backKernels are processes that run interactive code in a particular programming language and return output to the user. Kernels also respond to tab completion and introspection requests.
Go back


Node.js and ES6 Instead of Java – A War Story
by Patrick Hund
We created a Node.js web app from scratch within 9 weeks that now serves 10.81 million visitors each month*. We used the latest and greatest incarnation of JavaScript – ECMAScript 2015, a.k.a. ES6 – for the backend and frontend alike. We spent late nights coding in gleeful frenzy, stepped into pitfalls, moaned about WTFs, scaled the dizzy heights of asynchronicity. This is our story.
* AGOF Digital Facts 2015-06
Hi, I'm Patrick, software engineer. My team and I work for mobile.de, which is Germany's biggest online marketplace for cars and other vehicles.
In June 2015, we were given a task that every software developer dreams of: throw away all the old stuff and rewrite everything from scratch. The “old stuff” being the home page of mobile.de, the main entry point to our platform.
mobile.de before…
…and after the relaunch
Why Node.js?
We have traditionally been a Java shop since we migrated from a big steaming pile of Perl back in 2007. But engineers at mobile.de are encouraged to explore new technologies and empowered to choose the best tool for the task at hand and the given team setup.
It was not hard to convince the Powers That BeTM that we should go for Node.js, although it was still fairly new technology for us.
Our system architecture has been evolving from monolithic to service-oriented in the last years. The new home page was to become a fairly simple web application, basically a thin layer between a handful of service APIs and the client-side code. Node.js is great at integrating services and passing data through to the presentation layer, so it was an obvious choice.
A thin layer between services and client
We had a fairly tough deadline to meet, which is unusual for our company, but could not be avoided in this case. The new face of mobile.de needed to beam at the world on September 1st 2015, leaving us about 9 weeks.
At the time we started, our team included four JavaScript experts (including myself) and two Java experts, one of whom was on vacation until well into the project. After some experimentation with PayPal's kraken.js framework, I was confident that we could pull this off with much less deadline risk than using the “traditional” Spring/Java stack (more on why using Kraken turned out to be not such a great idea later).
Main concerns of our management were system stability, scalability and monitoring. We took a lot of effort to make sure these requirements were met. More on this in another blog article by my team mate Jonathan Krause (coming soon).
For further reading on why JavaScript is a good choice for backend and frontend alike, here is a link to a great article by Eric Elliott, How to Build a High Velocity Development Team, section “Why Language Matters”.
Setting Up the Build System
The Trouble With Kraken
The first phase of our project was to set up the basic scaffold of the application, including a build system that allows us to smoothly and quickly work on the software running in our local development environments.
When I evaluated PayPal's kraken.js framework early in 2015, I was euphoric about it: you run a Yeoman generator, and it sets up a basic skeleton app with Express, Dust.js templates, a Grunt build system, Bower package manager integration and a dev server that allows live reloading – everything we needed, ready to use within seconds. Heaven!
Unfortunately, when I set out to use Kraken in earnest, it turned out that the project had not been updated since April 2015 (v2.0.0-rc1). A new 2.x version has not been released ever since (at the time I'm writing this, October 2015).
So I had a choice to make:
- use the old but stable 1.x version of Kraken
- use the newer, but unstable RC version of Kraken 2
- don't use Kraken framework as a whole, only single Kraken modules; set up the whole build system myself
My engineer's heart that wants to use the latest and greatest and try out cool and new stuff got the better of me and defeated the voice of reason (also known as “The You-Have-a-Deadline-Dude”) – so of course, I went for the latter option.
Engineering Man vs. Deadline Dude
The reasoning behind this decision:
- I did not want to risk being stuck with outdated software and be at the mercy of our (highly respected!) colleagues at PayPal to eventually provide an update that we can migrate to with reasonable effort
- I wanted to use the latest version of JavaScript, ECMAScript 2015 (ES6) for backend and frontend, which would take a lot of customization to bake into the Kraken scaffold
- Likewise, I wanted to use webpack for optimizing and bundling client-side resources; webpack had proven indispensable at my previous project, the relaunch of the search results page of mobile.de
webpack – Great for Frontend, Also Backend?
During my research, I came across an interesting series of blog articles by Mozilla developer James Long, Backend Apps with webpack.
James explores the possibility to use webpack not only to bundle and optimize client-side JavaScript and CSS resources, but also the backend JavaScript code that runs on NodeJS.
I set up our build system based on his article: npm run-script commands run Gulp tasks that use webpack for building and running the software.
I was aware that using webpack for the backend was an experiment, and it did turn out not to be feasible in the long run: maintaining the complex build configuration became too much of a hassle, so we recently decided to simplify things by using webpack only for the frontend.
For further reading on why webpack is awesome (for client-side resources), check out this blog article that I wrote on the subject.
Streaming Builds With Gulp
We had previously used Grunt as frontend build tool in almost all our projects. Gulp is an interesting alternative, as it uses the streaming API of Node.js, allowing for some fascinating code solutions.
The Engineering Man in me still likes Gulp better than Grunt, but in hindsight, we should have gone with Deadline Dude's recommendation to stick to Grunt, as this would have allowed us to set up and maintain the build system much quicker – Gulp's streaming API has a steep learning curve.
It also turned out that some of the available Gulp plugins did not work 100% percent when running on our Jenkins CI system, causing hanging builds, which we only managed to fix by setting up some Gulp tasks to run sequentially. This defeats one of Gulp's selling points over Grunt, the ability to run tasks in parallel.
Demo: Local Development
To show you how nice it is to work on a Node.js project with a good build system, I've created a short demo video.
I especially like the live reloading provided by the webpack dev server that allows me to make changes to Less stylesheets and client-side JavaScript without having to hit the reload button of my browser all the time.
Thanks to sourcemaps, I can inspect my CSS and JavaScript code in the browser, which shows me the original ES6 and Less source files.
When I work on the backend, I also have very short turnaround cycles – nodemon detects changes of the backend ES6 code and restarts the application for me, which only takes 200-400 milliseconds. Compared to working on a Java application, where recompiling and restarting takes a perceived eternity, this is incredible.
To Be Continued…
That's it for now – I have lots more to talk about, so look forward to the other two parts of this series, coming soon to the eBay Technology Blog:
- Part II: Practical application of ES6 features – working with Dust templates – MVC architecture with Express – unit tests with Mocha, Chai and Sinon
- Part III: Lessons learned from building a Node.js application from scratch in 9 weeks
My team mate Jonathan Krause also wrote an excellent article about how we run our webapp in production (deployment, monitoring and logging): Node.js for the Real World
If you want to make sure you don't miss an episode, feel free to follow me on Twitter. 😊
Acknowledgements
- Ice Cubes photograph by Darren Hester


Galaxy is a web-based data analysis framework for comparative genomics. It exists in two flavors:
Galaxy aims to be a zero configuration entirely self contained system, that provides a lightweight webserver, an embedded database and a multi-threaded job manager. Tools (and their parameters) can be specified via simple XML based configuration files. Galaxy allows you to deploy a wide variety of bioinformatics tools through the web. It renders all HTML widgets the tools need, verifies inputs, and stores and manages the outputs that these tools create.
The Center for Comparative Genomics and Bioinformatics at Penn State | 2005


Match Play. Double Match Point. How should Red play 54?
pips Red=112 White=153
(CorrectAnswer= 0/0, ErrorScore= 0)
As you might expect, paying now with 13/8, 10/6 is the correct play, paying now while White’s home board is so weak.
What is surprising is that the safe play, 10/5, 8/4 is not quite an error. This is partly because the safe play gives Red a good distribution and partly because it is surprising how quickly White can build an attack against the lone Red checker if it is hit initially.
What is surprising is that the safe play, 10/5, 8/4 is not quite an error. This is partly because the safe play gives Red a good distribution and partly because it is surprising how quickly White can build an attack against the lone Red checker if it is hit initially.
1. Cubeful 2-ply 10/5 8/4 Eq.: +0.492 0.746 0.134 0.002 - 0.254 0.026 0.000 2. Cubeful 2-ply 13/8 10/6 Eq.: +0.477 (-0.014) 0.739 0.191 0.008 - 0.261 0.034 0.001 3. Cubeful 2-ply 10/5 6/2 Eq.: +0.453 (-0.039) 0.727 0.128 0.002 - 0.273 0.031 0.000 4. Cubeful 2-ply 10/1 Eq.: +0.453 (-0.039) 0.726 0.125 0.002 - 0.274 0.030 0.000 5. Cubeful 2-ply 8/4 6/1 Eq.: +0.432 (-0.060) 0.716 0.206 0.010 - 0.284 0.046 0.001


SITE_NAME ping endpoints accept HTTP HEAD, GET and POST request methods.
When using HTTP POST, you can include an arbitrary payload in the request body. SITE_NAME will log the first 10 kilobytes (10 000 bytes) of the request body, so that you can inspect it later.
In this example, we run certbot renew
, capture its output (both the stdout
and stderr streams), and submit the captured output to SITE_NAME:
#!/bin/sh
m=$(/usr/bin/certbot renew 2>&1)
curl -fsS -m 10 --retry 5 --data-raw "$m" PING_URL
/fail
and /{exit-status}
EndpointsWe can extend the previous example and signal either success or failure depending on the exit code:
#!/bin/sh
m=$(/usr/bin/certbot renew 2>&1)
curl -fsS -m 10 --retry 5 --data-raw "$m" PING_URL/$?
Runitor is a third party utility that runs the supplied command, captures its output and reports to SITE_NAME. It also measures the execution time and retries HTTP requests on transient errors. Best of all, the syntax is simple and clean:
runitor -uuid your-uuid-here -- /usr/bin/certbot renew
You may sometimes want to log diagnostic information without altering the check's current state. SITE_NAME provides the /log endpoint just for that. When you send an HTTP POST request to this endpoint, SITE_NAME will log the event and display it in check's "Events" section, but will keep the check's state unchanged.
While SITE_NAME can store a small amount of logs in a pinch, it is not specifically designed for that. If you run into the issue of logs getting cut off, consider the following options:
dmesg
output:#!/bin/sh
m=$(dmesg | tail --bytes=10000)
curl -fsS -m 10 --retry 5 --data-raw "$m" PING_URL
In the check's details page, Events section, click on individual events to see full event details, including the captured log information.
In the dialog that opens, use the "Download Original" link to download the request body data, exactly as it was submitted to SITE_NAME:


Mandor Mountains [at23], mountain, in Mandoria, wilderness
Last updated Turn #138
Mandor Mountains [at23], mountain, in Mandoria, wilderness
------------------------------------------------------------------------
6: Osmosis [o2n], Imperial Empire, priest of the Church of Halon [157],
6: with 47 nazgul, arrived from the south, accompanied by:
6: Sir Andrew [v9a], Imperial Empire, priest of the Church of
6: Halon [157], with 48 nazgul
6: Vroomfondel [o9a], Mandor Confederacy, prisoner
6: Klael [d5o], Mandor Confederacy, mage, prisoner
6: Demon lord [gt0t], demon lord, refugee, prisoner
7: Osmosis [o2n], Imperial Empire, priest of the Church of Halon [157],
7: with 47 nazgul, left for Another mine [p95], accompanied by:
7: Sir Andrew [v9a], Imperial Empire, priest of the Church of
7: Halon [157], with 48 nazgul
7: Vroomfondel [o9a], Mandor Confederacy, prisoner
7: Klael [d5o], Mandor Confederacy, mage, prisoner
7: Demon lord [gt0t], demon lord, refugee, prisoner
10: Osmosis [o2n], Imperial Empire, priest of the Church of Halon [157],
10: with 44 nazgul, 13 lt. xbowmen, 27 wild horses, two warmounts,
10: six riding horses, arrived from Another mine [p95], accompanied by:
10: Sir Andrew [v9a], Imperial Empire, priest of the Church of
10: Halon [157], with 47 nazgul
10: Vroomfondel [o9a], Mandor Confederacy, prisoner
10: Klael [d5o], Mandor Confederacy, mage, prisoner
10: Demon lord [gt0t], demon lord, refugee, prisoner
10: Lactus [u6q], Mandor Confederacy, prisoner
10: Mongoose [e6z], Mandor Confederacy, knight, prisoner
10: Lady A [x2x], Mandor Confederacy, knight, prisoner
10: Pickaxe Joe [w4b], Mandor Confederacy, prisoner
10: Osmosis [o2n], Imperial Empire, priest of the Church of Halon [157],
10: with 44 nazgul, 13 lt. xbowmen, went east, accompanied by:
10: Sir Andrew [v9a], Imperial Empire, priest of the Church of
10: Halon [157], with 47 nazgul
10: Vroomfondel [o9a], Mandor Confederacy, prisoner
10: Klael [d5o], Mandor Confederacy, mage, prisoner
10: Demon lord [gt0t], demon lord, refugee, prisoner
10: Lactus [u6q], Mandor Confederacy, prisoner
10: Mongoose [e6z], Mandor Confederacy, knight, prisoner
10: Lady A [x2x], Mandor Confederacy, knight, prisoner
10: Pickaxe Joe [w4b], Mandor Confederacy, prisoner
Routes leaving Mandor Mountains:
East, mountain, to Mandor Mountains [at24], 10 days
South, plain, to Open Pampas [au23], 7 days
West, plain, to Open Pampas [at22], 7 days
Garrison [iy1u], garrison, uncontrolled, with six peasants
Down, mine-shaft, to Another mine [p95], 0 days
Seen here:
Stack of giants [ag2b], giants, number: 12


Using wasm plugins
WebAssembly (WASM) is a simple machine model and executable format with an extensive specification. It is designed to be portable, compact, and execute at or near native speeds. Otoroshi already supports the execution of WASM files by providing different plugins that can be applied on routes. You can find more about those plugins here
To simplify the process of WASM creation and usage, Otoroshi provides:
- otoroshi ui integration: a full set of plugins that let you pick which WASM function to runtime at any point in a route
- otoroshi
wasm-manager
: a code editor in the browser that let you write your plugin inRust
,TinyGo
,Javascript
orAssembly Script
without having to think about compiling it to WASM (you can find a complete tutorial about it here)
Tutorial
- Before your start
- Create the route with the plugin validator
- Test your validator
- Update the route by replacing the backend with a WASM file
- WASM backend test
After completing these steps you will have a route that uses WASM plugins written in Rust.
Before your start
If you already have an up and running otoroshi instance, you can skip the following instructions
Let’s start by downloading the latest Otoroshi.
curl -L -o otoroshi.jar 'https://github.com/MAIF/otoroshi/releases/download/v16.8.0-dev/otoroshi.jar'
then you can run start Otoroshi :
java -Dotoroshi.adminPassword=password -jar otoroshi.jar
Now you can log into Otoroshi at http://otoroshi.oto.tools:8080 with<EMAIL_ADDRESS>Create a new route, exposed on http://myservice.oto.tools:8080
, which will forward all requests to the mirror https://mirror.otoroshi.io
. Each call to this service will returned the body and the headers received by the mirror.
curl -X POST 'http://otoroshi-api.oto.tools:8080/api/routes' \
-H "Content-type: application/json" \
-u admin-api-apikey-id:admin-api-apikey-secret \
-d @- <<'EOF'
{
"name": "my-service",
"frontend": {
"domains": ["myservice.oto.tools"]
},
"backend": {
"targets": [
{
"hostname": "mirror.otoroshi.io",
"port": 443,
"tls": true
}
]
}
}
EOF
Create the route with the plugin validator
For this tutorial, we will start with an existing wasm file. The main function of this file will check the value of an http header to allow access or not. The can find this file at https://raw.githubusercontent.com/MAIF/otoroshi/master/demos/wasm/first-validator.wasm
The main function of this validator, written in rust, should look like:
- validator.rs
-
mod types; use extism_pdk::*; #[plugin_fn] pub fn execute(Json(context): Json<types::WasmAccessValidatorContext>) -> FnResult<Json<types::WasmAccessValidatorResponse>> { let out = types::WasmAccessValidatorResponse { result: false, error: Some(types::WasmAccessValidatorError { message: "you're not authorized".to_owned(), status: 401 }) }; match context.request.headers.get("foo") { Some(foo) => if foo == "bar" { Ok(Json(types::WasmAccessValidatorResponse { result: true, error: None })) } else { Ok(Json(types::WasmAccessValidatorResponse { result: false, error: Some(types::WasmAccessValidatorError { message: format!("{} is not authorized", foo).to_owned(), status: 401 }) })) }, None => Ok(Json(out)) } }
- validator.js
-
export function execute() { let context = JSON.parse(Host.inputString()); if (context.request.headers["foo"] === "bar") { const out = { result: true }; Host.outputString(JSON.stringify(out)); } else { const error = { result: false, error: { message: "you're not authorized", status: 401 } }; Host.outputString(JSON.stringify(error)); } return 0; }
- validator.ts
-
import { WasmAccessValidatorContext, WasmAccessValidatorResponse } from './types'; export declare var Host: any; export function execute() { let context = JSON.parse(Host.inputString()) as WasmAccessValidatorContext; if (context.request.headers["foo"] === "bar") { const out: WasmAccessValidatorResponse = { result: true }; Host.outputString(JSON.stringify(out)); } else { const error: WasmAccessValidatorResponse = { result: false, error: { message: "you're not authorized", status: 401 } }; Host.outputString(JSON.stringify(error)); } return 0; }
- validator.js
-
export function execute() { let context = JSON.parse(Host.inputString()); if (context.request.headers["foo"] === "bar") { const out = { result: true }; Host.outputString(JSON.stringify(out)); } else { const error = { result: false, error: { message: "you're not authorized", status: 401 } }; Host.outputString(JSON.stringify(error)); } return 0; }
- validator.go
-
package main import ( "github.com/extism/go-pdk" "github.com/buger/jsonparser" ) //export execute func execute() int32 { input := pdk.Input() var foo, err = jsonparser.GetString(input, "request", "headers", "foo") if err != nil {} var output = "" if foo == "bar" { output = `{ "result": true }` } else { output = `{ "result": false, "error": { "message": "you're not authorized", "status": 401 } }` } mem := pdk.AllocateString(output) pdk.OutputMemory(mem) return 0 } func main() {}
The plugin receives the request context from Otoroshi (the matching route, the api key if present, the headers, etc) as WasmAccessValidatorContext
object. Then it applies a check on the headers, and responds with an error or success depending on the content of the foo header. Obviously, the previous snippet is an example and the editor allows you to write whatever you want as a check.
Let’s create a route that uses the previous wasm file as an access validator plugin :
curl -X POST "http://otoroshi-api.oto.tools:8080/api/routes" \
-H "Content-type: application/json" \
-u admin-api-apikey-id:admin-api-apikey-secret \
-d @- <<'EOF'
{
"id": "demo-otoroshi",
"name": "demo-otoroshi",
"frontend": {
"domains": ["demo-otoroshi.oto.tools"]
},
"backend": {
"targets": [
{
"hostname": "mirror.otoroshi.io",
"port": 443,
"tls": true
}
],
"load_balancing": {
"type": "RoundRobin"
}
},
"plugins": [
{
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"enabled": true
},
{
"plugin": "cp:otoroshi.next.plugins.WasmAccessValidator",
"enabled": true,
"config": {
"source": {
"kind": "http",
"path": "https://raw.githubusercontent.com/MAIF/otoroshi/master/demos/wasm/first-validator.wasm",
"opts": {}
},
"memoryPages": 4,
"functionName": "execute"
}
}
]
}
EOF
This request will apply the following process:
- names the route demo-otoroshi
- creates a frontend exposed on the
demo-otoroshi.oto.tools
- forward requests on one target, reachable at
mirror.otoroshi.io
using TLS on port 443 - adds the WasmAccessValidator plugin to validate access based on the foo header to the route
You can validate the route creation by navigating to the dashboard
Test your validator
curl "http://demo-otoroshi.oto.tools:8080" -I
This should output the following error:
HTTP/1.1 401 Unauthorized
Let’s call again the route by adding the header foo with the bar value.
curl "http://demo-otoroshi.oto.tools:8080" -H "foo:bar" -I
This should output the successfull message:
HTTP/1.1 200 OK
Update the route by replacing the backend with a WASM file
The next step in this tutorial is to use a WASM file as backend of the route. We will use an existing WASM file, available in our wasm demos repository on github. The content of this plugin, called wasm-target.wasm
, looks like:
- target.rs
-
// (1) mod types; // (2) use extism_pdk::*; use std::collections::HashMap; #[plugin_fn] pub fn execute(Json(context): Json<types::WasmQueryContext>) -> FnResult<Json<types::WasmQueryResponse>> { // (3) let mut headers = HashMap::new(); headers.insert("foo".to_string(), "bar".to_string()); // (4) let response = types::WasmQueryResponse { headers: Some(headers.into_iter().chain(context.raw_request.headers).collect()), body: "{\"foo\": \"bar\"}".to_owned(), status: 200 }; Ok(Json(response)) }
- target.js
-
// (2) export function execute() { let str = Host.inputString(); let context = JSON.parse(str); // (3) let headers = { ...context.request.headers }; headers["foo"] = "bar"; // (4) let response = { headers, body: "{\"foo\": \"bar\"}", status: 200 }; Host.outputString(JSON.stringify(response)); return 0; }
- target.ts
-
// (1) import { WasmQueryContext, WasmQueryResponse } from './types'; export declare var Host: any; // (2) export function execute() { const context = JSON.parse(Host.inputString()) as WasmQueryContext; // (3) const headers = { "foo": "bar", ...(context.request.headers || {}) } // (4) const response: WasmQueryResponse = { headers, status: 200, body: "{\"foo\": \"bar\"}" }; Host.outputString(JSON.stringify(response)); return 0; }
- target.js
-
// (2) export function execute() { let str = Host.inputString(); let context = JSON.parse(str); // (3) let headers = { ...context.request.headers }; headers["foo"] = "bar"; // (4) let response = { headers, body: "{\"foo\": \"bar\"}", status: 200 }; Host.outputString(JSON.stringify(response)); return 0; }
- target.go
-
package main // (1) import ( "github.com/extism/go-pdk" "github.com/buger/jsonparser" ) // (2) //export execute func execute() int32 { input := pdk.Input() // (3) var headers, dataType, offset, err = jsonparser.Get(input, "request", "headers") _ = dataType _ = offset if err != nil {} // (4) output := `{"headers":` + string(headers) + `, "body": {\"foo\": \"bar\"}, "status": 200 }` mem := pdk.AllocateString(output) pdk.OutputMemory(mem) return 0 } func main() {}
Let’s explain this snippet. The purpose of this type of plugin is to respond an HTTP response with http status, body and headers map.
- Includes all public structures from
types.rs
file. This file contains predefined Otoroshi structures that plugins can manipulate. - Necessary imports. Extism’s goal is to make all software programmable by providing a plug-in system.
- Creates a map of new headers that will be merged with incoming request headers.
- Creates the response object with the map of merged headers, a simple JSON body and a successfull status code.
The file is downloadable here.
Let’s update the route using the this wasm file.
curl -X PUT "http://otoroshi-api.oto.tools:8080/api/routes/demo-otoroshi" \
-H "Content-type: application/json" \
-u admin-api-apikey-id:admin-api-apikey-secret \
-d @- <<'EOF'
{
"id": "demo-otoroshi",
"name": "demo-otoroshi",
"frontend": {
"domains": ["demo-otoroshi.oto.tools"]
},
"backend": {
"targets": [
{
"hostname": "mirror.otoroshi.io",
"port": 443,
"tls": true
}
],
"load_balancing": {
"type": "RoundRobin"
}
},
"plugins": [
{
"plugin": "cp:otoroshi.next.plugins.OverrideHost",
"enabled": true
},
{
"plugin": "cp:otoroshi.next.plugins.WasmAccessValidator",
"enabled": true,
"config": {
"source": {
"kind": "http",
"path": "https://raw.githubusercontent.com/MAIF/otoroshi/master/demos/wasm/first-validator.wasm",
"opts": {}
},
"memoryPages": 4,
"functionName": "execute"
}
},
{
"plugin": "cp:otoroshi.next.plugins.WasmBackend",
"enabled": true,
"config": {
"source": {
"kind": "http",
"path": "https://raw.githubusercontent.com/MAIF/otoroshi/master/demos/wasm/wasm-target.wasm",
"opts": {}
},
"memoryPages": 4,
"functionName": "execute"
}
}
]
}
EOF
The response should contains the updated route content.
WASM backend test
Let’s call our route.
curl "http://demo-otoroshi.oto.tools:8080" -H "foo:bar" -H "fifi: foo" -v
This should output:
* Trying <IP_ADDRESS>:8080...
* Connected to demo-otoroshi.oto.tools (<IP_ADDRESS>) port 8080 (#0)
> GET / HTTP/1.1
> Host: demo-otoroshi.oto.tools:8080
> User-Agent: curl/7.79.1
> Accept: */*
> foo:bar
> fifi:foo
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< foo: bar
< Host: demo-otoroshi.oto.tools:8080
<
* Closing connection 0
{"foo": "bar"}
In this response, we can find our headers send in the curl command and those added by the wasm plugin.


The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator<EMAIL_ADDRESS>and inform them of the time the error occurred, and anything you might have done that may have caused the error.
More information about this error may be available in the server error log, unless you are using node.js
node fires are small but there are so many they will consume all your inodes


Huawei Y9s Officially Launched in Kenya
by George KamauEarly today, Huawei officially launched the Huawei Y9s and announced the Band 4 smartwatch series. Huawei recently announced they’ll be bringing these two devices, the Huawei Y9s and the Band 4 to the Kenyan market and now they’re finally here.
The Huawei Y9s is the company’s first phone in Kenya to rock a side-mounted fingerprint sensor.
Continuing its trend of ditching the notch for a full-screen experience, the Huawei Y9s comes with a pop-up selfie camera to give that almost bezel-less design. The 6.59″ LCD display is stunning and comes with a resolution of FHD+ at 2340×1080 and in a 19.5:9 aspect ratio.
That large display of the Huawei Y9s will offer you enough screen real-estate to consume multimedia content or for mobile gaming.
The back looks elegant too with he colour-gradient back and the Huawei Y9s comes in two colours – Midnight Black and Breathing Crystal. The back is curved to give a good grip for easy one-handed use.
For optics, the Huawei Y9s features 4 cameras: triple AI-powered rear cameras and a pop-up selfie camera. The main cameras include 48MP, an 8MP wide-angle camera and a 2MP depth sensor for bokeh shots.
 You’ll have to stay still though to capture shots in low light sceneries.
The 48MP sensor on the Huawei Y9s uses Quad-Bayer technology to combine four pixels into one for better low light performance.
For selfies, you get a 16MP camera that uses a pop-up mechanism that retracts the camera back into the phone’s body when the sensors notice a sharp and fast decline. Modes you can play around with include bokeh and beauty for those perfect selfies.
For assurance, the retractable camera has been tested thoroughly and can sustain up to 100,000 pop-ups.
Powering the Huawei Y9s is a 2.2Ghz octa-core Kirin 710F chip coupled with 6GB of RAM and 128GB of onboard storage. You can still expand the storage using an external micro-SD card. For gamers, the Huawei Y9s also rocks GPU Turbo 3.0.
The Huawei Y9s packs a 4000mAh battery plus feature smart power-saving options to increase its efficiency and give users extended battery life – It also sports a Type-C USB port. A 10W charger is provided.
A side-mounted fingerprint sensor and Face Unlock are present for biometrics.
The Huawei Y9s comes with Android Pie 9.0 and EMUI 9.1 skin with intelligent functions to help you be more efficient in your everyday tasks.
There are Google services included so you don’t have to worry about missing out on Android apps.
Pricing and Availability
The Huawei Y9s will start selling from Ksh 31,999 and you can pre-order it from today November 14th until the 28th of November to get a gift hamper that includes free wireless headphones.
Band 4 series
Huawei also took the stage to launch their smartwatch devices – the Band 4 series. The smartwatch is targetted at young consumers and features an ergonomic design and offers a couple of fitness-focussed features plus on the go alerts for incoming calls and message notifications from a connected phone.
You get a 2.5D colourful touch screen and charges via a built-in USB plug for easy charging. There are also multiple workout modes that range from outdoor and indoor run, walk, cycle, elliptical to free training.
When you connect your device to the Band 4, you get other features such as Find My Phone and Remote Shutter.
For customization, you get to play around faces of different styles from the Huawei Watch Face Store.
The Band 4 and the smaller Band 4e start selling from Ksh 4,999 and Ksh 3,199 respectively.