Author: tchemit Date: 2009-09-20 19:12:37 +0200 (Sun, 20 Sep 2009) New Revision: 189 Added: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/jredmine_controller.rb jredmine/trunk/jredmine-client/src/site/apt/rails_api.apt Removed: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/rest_controller.rb Modified: jredmine/trunk/jredmine-client/pom.xml jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/DefaultRedmineService.java jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineService.java jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineServiceImplementor.java jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/rest/RedmineRestClient.java jredmine/trunk/jredmine-client/src/main/redmine/jredmine/init.rb jredmine/trunk/jredmine-client/src/site/apt/index.apt jredmine/trunk/jredmine-client/src/site/site.xml Log: add javadoc add site documentation consolidate jredmine rails plugin improve plexus components Modified: jredmine/trunk/jredmine-client/pom.xml =================================================================== --- jredmine/trunk/jredmine-client/pom.xml 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/pom.xml 2009-09-20 17:12:37 UTC (rev 189) @@ -61,29 +61,12 @@ </exclusions> </dependency> - <!-- <dependency> - <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-utils</artifactId> - </dependency>--> - <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <scope>test</scope> </dependency> - <!-- fix dependency in xpp parsing from plexus (need at least version > 2.2) --> - <!--<dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - </dependency>--> - - <!-- fix dependency in maven-helper-plugin --> - <!--<dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> - </dependency>--> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> @@ -110,12 +93,12 @@ <!-- expose new plexus components --> <plugin> <groupId>org.codehaus.plexus</groupId> - <artifactId>plexus-maven-plugin</artifactId> - <version>1.3.8</version> + <artifactId>plexus-component-metadata</artifactId> + <version>1.2.0</version> <executions> <execution> <goals> - <goal>descriptor</goal> + <goal>generate-metadata</goal> </goals> </execution> </executions> @@ -135,6 +118,16 @@ </plugins> </build> + + <reporting> + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>1.3.8</version> + </plugin> + </plugins> + </reporting> <!-- ************************************************************* --> <!-- *** Build Environment ************************************** --> <!-- ************************************************************* --> Modified: jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/DefaultRedmineService.java =================================================================== --- jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/DefaultRedmineService.java 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/DefaultRedmineService.java 2009-09-20 17:12:37 UTC (rev 189) @@ -36,10 +36,12 @@ protected static final Log log = LogFactory.getLog(DefaultRedmineService.class); /** * client Rest + * @plexus.requirement role="org.nuiton.io.rest.RestClient" + * role-hint="redmine" */ protected RestClient session; /** - * xpp3 xpp3Helper + * xpp3 xpp3Helper to transform xml stream to pojo */ protected final RedmineXpp3Helper xpp3Helper; /** @@ -191,12 +193,13 @@ @Override public RedmineServiceImplementor init(RestClientConfiguration configuration) throws RedmineServiceException { - RedmineServiceImplementor result = init(new RedmineRestClient(configuration)); + session.setConfiguration(configuration); + RedmineServiceImplementor result = init(session); return result; } @Override - public RedmineServiceImplementor init(RedmineRestClient session) throws RedmineServiceException { + public RedmineServiceImplementor init(RestClient session) throws RedmineServiceException { if (init) { throw new IllegalStateException("the client " + this + " was already init!"); } @@ -283,7 +286,7 @@ String requestName = type.getName() + (array ? "list" : "detail"); RestRequest r = getRequest(requestName, args); - // obtain data from rest session + // obtain data from rest client try { InputStream stream = session.askData(r); Modified: jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineService.java =================================================================== --- jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineService.java 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineService.java 2009-09-20 17:12:37 UTC (rev 189) @@ -14,8 +14,6 @@ /** * The service that mirrors the rails {@code jredmine} plugin. * - * TODO javadoc - * * @author chemit * @since 1.0.0 */ @@ -24,35 +22,172 @@ /** Plexus lookup name */ String ROLE = RedmineService.class.getName(); + /** + * Obtain all accessible projets for the loggued user. + * + * @return all the projects + * @throws RedmineServiceException if any pb + * @see Project + */ Project[] getProjects() throws RedmineServiceException; + /** + * Obtain all the priorities defined on a {@link Issue}. + * + * <b>Note : </b> The priorities are common for all projects. + * + * @return all the issue properties + * @throws RedmineServiceException + * @see IssuePriority + */ IssuePriority[] getIssuePriorities() throws RedmineServiceException; + /** + * Obtain all the statuses defined on a {@link Issue}. + * + * <b>Note : </b> The statuses are common for all projects. + * + * @return all the issue statuses + * @throws RedmineServiceException + * @see IssueStatus + */ IssueStatus[] getIssueStatuses() throws RedmineServiceException; + /** + * Obtain a project given his name. + * + * @param projectId the name of the project + * @return the project + * @throws RedmineServiceException + * @see Project + */ Project getProject(String projectId) throws RedmineServiceException; + /** + * Obtain all categories defined on issues for a given project. + * + * @param projectId the name of the project + * @return the categories of issues for the given project. + * @throws RedmineServiceException + * @see IssueCategory + */ IssueCategory[] getIssueCategories(String projectId) throws RedmineServiceException; + /** + * Obtain all trackers defined on a given project. + * + * @param projectId the name of the project + * @return the trackers for the given project. + * @throws RedmineServiceException + * @see Tracker + */ Tracker[] getTrackers(String projectId) throws RedmineServiceException; + /** + * Obtain all news defined on a given project. + * + * @param projectId the name of the project + * @return the news for the given project. + * @throws RedmineServiceException + * @see News + */ News[] getNews(String projectId) throws RedmineServiceException; + /** + * Obtain all users defined on a given project. + * + * @param projectId the name of the project + * @return the users for the given project. + * @throws RedmineServiceException + * @see User + */ User[] getUsers(String projectId) throws RedmineServiceException; + /** + * Obtain all versions defined on a given project. + * + * @param projectId the name of the project + * @return the versions of the given project. + * @throws RedmineServiceException + * @see Version + */ Version[] getVersions(String projectId) throws RedmineServiceException; + /** + * Obtain a specific version for a given project. + * + * @param projectId the name of the project + * @param versionId the name of the version + * @return the version + * @throws RedmineServiceException + * @see Version + */ Version getVersion(String projectId, String versionId) throws RedmineServiceException; + /** + * Obtain all issues for a specific version on a given project + * + * @param projectId the name of the project + * @param versionId the name of the version + * @return the issues + * @throws RedmineServiceException + * @see Issue + */ Issue[] getIssues(String projectId, String versionId) throws RedmineServiceException; + /** + * Obtain all attachments for a specific version on a given project + * + * @param projectId the name of the project + * @param versionId the name of the version + * @return the attachments + * @throws RedmineServiceException + * @see Attachment + */ Attachment[] getAttachments(String projectId, String versionId) throws RedmineServiceException; + /** + * Add a version for a given project. + * + * @param projectId the name of the project + * @param version the version to add + * @return the added version + * @throws RedmineServiceException + * @see Version + */ Version addVersion(String projectId, Version version) throws RedmineServiceException; + /** + * Update a version for a given project. + * + * @param projectId the name of the project + * @param version the version to update + * @return the updated version + * @throws RedmineServiceException + * @see Version + */ Version updateVersion(String projectId, Version version) throws RedmineServiceException; + /** + * Add a news for a given project. + * + * @param projectId the name of the project + * @param news the news to add + * @return the added news. + * @throws RedmineServiceException + * @see News + */ News addNews(String projectId, News news) throws RedmineServiceException; + /** + * Add a attachment for a given version of a given project. + * + * @param projectId the name of the project + * @param versionId the name of the version + * @param attachement the attachment to add + * @return the added attachment + * @throws RedmineServiceException + * @see Attachment + */ Attachment addAttachment(String projectId, String versionId, Attachment attachement) throws RedmineServiceException; } Modified: jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineServiceImplementor.java =================================================================== --- jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineServiceImplementor.java 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/RedmineServiceImplementor.java 2009-09-20 17:12:37 UTC (rev 189) @@ -1,30 +1,96 @@ package org.nuiton.jredmine; import java.io.InputStream; +import org.nuiton.io.rest.RestClient; import org.nuiton.io.rest.RestClientConfiguration; import org.nuiton.jredmine.rest.RedmineRestClient; /** * Technical contrat te be implemented in a {@link RedmineService}. * + * Any concrete implentation of a {@link RedmineService} should also implements + * this service. + * * @author chemit * @since 1.0.0 */ public interface RedmineServiceImplementor { + /** + * Tests if the service is loogued to the redmine service. + * + * @return {@code true} is service is init and loggued to Redmine service, + * {@code false} otherwise. + */ boolean isInit(); - RedmineServiceImplementor init(RedmineRestClient session) throws RedmineServiceException; + /** + * Initialize the service given a redmine client already initialized. + * + * @param client the redmine client to be used by the service + * @return the initialized service + * @throws RedmineServiceException + * @see RedmineRestClient + */ + RedmineServiceImplementor init(RestClient client) throws RedmineServiceException; + /** + * Initialize the service given a client configuration. + * + * @param configuration the configuration to be used to init the internal redmine client + * @return the initialized service + * @throws RedmineServiceException + */ RedmineServiceImplementor init(RestClientConfiguration configuration) throws RedmineServiceException; + /** + * Close the service and destroy any connexions to the redmine service. + * + * @throws RedmineServiceException + */ void destroy() throws RedmineServiceException; + /** + * Generic method to obtain a single data from a redmine server. + * + * @param <T> the type of data to obtain + * @param type the type of data to obtain + * @param args the parameters to obtain the data + * @return the obtained data + * @throws RedmineServiceException + */ <T> T getData(Class<T> type, Object... args) throws RedmineServiceException; + /** + * Generic method to obtain a array of data from a redmine server. + * + * @param <T> the type of data to obtain + * @param type the type of data to obtain + * @param args the parameters to obtain the datas + * @return the obtained datas + * @throws RedmineServiceException + */ <T> T[] getDatas(Class<T> type, Object... args) throws RedmineServiceException; + /** + * Generic method to obtain an input stream of a data from a redmine server. + * + * @param <T> the type of data to obtain + * @param type the type of data to obtain + * @param args the parameters to obtain the data + * @return the input stream containing the data + * @throws RedmineServiceException + */ <T> InputStream getDataStream(Class<T> type, Object... args) throws RedmineServiceException; + /** + * Generic method to obtain an input stream of an array of data from a redmine server. + * + * @param <T> the type of data to obtain + * @param type the type of data to obtain + * @param args the parameters to obtain the datas + * @return the input stream containing the datas + * @throws RedmineServiceException + */ <T> InputStream getDatasStream(Class<T> type, Object... args) throws RedmineServiceException; } Modified: jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/rest/RedmineRestClient.java =================================================================== --- jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/rest/RedmineRestClient.java 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/java/org/nuiton/jredmine/rest/RedmineRestClient.java 2009-09-20 17:12:37 UTC (rev 189) @@ -32,6 +32,9 @@ * * @author chemit * @since 1.0.0 + * + * @plexus.component role="org.nuiton.io.rest.RestClient" + * role-hint="redmine" */ public class RedmineRestClient extends RestClient { @@ -57,9 +60,17 @@ public static final String LOGOUT = "logout"; public static final String PING = "ping"; + public RedmineRestClient() { + super(); + } + public RedmineRestClient(RestClientConfiguration configuration) { super(configuration); + } + @Override + protected void addDefaultRequests() { + addRequestBuilder(new DefaultRequestBuilder(PING, "ping")); addRequestBuilder(new DefaultRequestBuilder(LOGOUT, "logout")); addRequestBuilder(new DefaultRequestBuilder(LOGIN, "login") { @@ -99,9 +110,9 @@ public String[] getParameters(Object... args) { Version version = (Version) args[1]; return new String[]{ - "version", version.getName(), - "description", version.getDescription(), - "date", DATE_FORMAT.format(version.getEffectiveDate()) + "version[name]", version.getName(), + "version[description]", version.getDescription(), + "version[effective_date]", DATE_FORMAT.format(version.getEffectiveDate()) }; } }); @@ -111,9 +122,9 @@ public String[] getParameters(Object... args) { Version version = (Version) args[1]; return new String[]{ - "version", version.getName(), - "description", version.getDescription(), - "date", DATE_FORMAT.format(version.getEffectiveDate()) + "version[name]", version.getName(), + "version[description]", version.getDescription(), + "version[effective_date]", DATE_FORMAT.format(version.getEffectiveDate()) }; } }); @@ -126,8 +137,7 @@ return new String[]{ "news[title]", news.getTitle(), "news[summary]", news.getSummary(), - "news[description]", news.getDescription(), - "authorId", news.getAuthorId() + "" + "news[description]", news.getDescription() }; } }); Copied: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/jredmine_controller.rb (from rev 185, jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/rest_controller.rb) =================================================================== --- jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/jredmine_controller.rb (rev 0) +++ jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/jredmine_controller.rb 2009-09-20 17:12:37 UTC (rev 189) @@ -0,0 +1,351 @@ +class JredmineController < ActionController::Base + + # find user (after login) + before_filter :find_user, :except => [:ping, :login] + + # find project and check permission + before_filter :find_project, :except => [:ping, :login, :logout, :get_projects, :get_issue_statuses, :get_issue_priorities] + + # find project's version + before_filter :find_version, :only => [:get_version, :get_version_issues, :get_version_attachments, :add_version_attachment] + + # check can edit project before push requests + #before_filter :check_edit, :only => [:add_version, :update_version, :add_news, :add_attachment, :add_version_attachment] + + # ping service (just to test if service is reachable) + def ping + render :text => "ping", :status => 200 + end + + # Login request and validation + def login + if !request.post? + # Logout user : get method not possible + self.logged_user = nil + render_status 405, "POST method required" + else + # Authenticate user + user = User.try_to_login(params[:username], params[:password]) + if user.nil? + # Invalid credentials + render_status 401, "Invalid credentials" + elsif user.new_record? + # Onthefly creation failed, + render_status 401, "User not activated" + else + # Valid user + self.logged_user = user + # always generate a key and set autologin cookie + token = Token.create(:user => user, :action => 'autologin') + cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now } + render_status 200, "User logged in" + end + end + end + + # Log out current user and redirect to welcome page + def logout + cookies.delete :autologin + Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? + # user is no more connected + self.logged_user = nil + render_status 200, "User logged out" + end + + # recuperation des projets + def get_projects + @projects = Project.find(:all) + render_array_result @projects, "projects" + end + + # recuperation des priorities d'issues + def get_issue_priorities + get_enumeration "IPRI" + end + + # recuperation des differentes categories d'issues + def get_issue_categories + @issue_categories = @project.issue_categories.find(:all) + render_array_result @issue_categories, "issue_categories" + end + + # recuperation des differentes statuts d'issues + def get_issue_statuses + @issue_status = IssueStatus.find(:all) + render_array_result @issue_status, "issue_statuses" + end + # recuperation du projet + def get_project + render_result @project + end + + # recuperation de tous les membres d'un projet + def get_project_users + @members = @project.members.find(:all) + @r = [] + for m in @members + u = User.find(m[:user_id]) + u[:role_id] = m[:role_id] + u[:member_id] = m[:id] + #TODO - should remove the hashed password ? + @r << u + end + render_array_result @r, "users" + end + + # recuperation de toutes les annonces d'un projet + def get_project_news + @news = @project.news.find(:all) + render_array_result @news, "news" + end + + # recuperation des trakers d'un projet + def get_project_trackers + @trackers = @project.trackers.find(:all) + render_array_result @trackers, "trackers" + end + + # recuperation des versions d'un projet + def get_project_versions + @versions = @project.versions.find(:all) + render_array_result @versions, "versions" + end + + # recuperation de la version d'un projet + def get_version + render_result @version + end + + # recuperation des issues d'un projet pour une version donnee + def get_version_issues + @issues = @version.fixed_issues.find(:all) + render_array_result @issues, "issues" + end + + # recuperation des pieces jointes d'un projet pour une version donnee + def get_version_attachments + @files = @version.attachments.find(:all) + render_array_result @files, "attachments" + end + + def show_permissions + allowed_permissions + render_result @allowed_permissions + end + + def show_actions + allowed_actions + render_result @allowed_actions + end + + # add a new version for a given project + def add_version(version = params["version"]) + if !request.post? + render_status 405, "POST method required for action add_version" + return false + end + @version = @project.versions.find_by_name(version[:name]) + if !@version + allowed = User.current.allowed_to?({:controller => 'projects', :action => "add_version"}, @project) + if !allowed + render_status 401, "No permission to add a version" + else + @version = Version.create(:project => @project, :name => version[:name]) + if version[:description] + @version['description'] = version[:description] + end + if version[:effective_date] + @version['effective_date'] = version[:effective_date] + end + if @version.save + render_result @version + else + render_status 505, "Could not add the version..." + end + end + else + render_result @version + end + end + + # update a existing version for a given project + def update_version(version=params["version"]) + if !request.post? + render_status 405, "POST method required for action update_version" + return false + end + @version = @project.versions.find_by_name(version[:name]) + if !@version + render_status 404, "The version " + version + " does not exist, can not update it..." + else + allowed = User.current.allowed_to?({:controller => 'versions', :action => "edit"}, @project) + if !allowed + render_status 401, "No permission to edit a version" + else + if version[:description] + @version['description'] = version[:description] + end + if version[:effective_date] + @version['effective_date'] = version[:effective_date] + end + if @version.save + render_result @version + else + render_status 505, "Could not update the version..." + end + end + end + end + + # add a new news for a given project + def add_news(news = params["news"]) + if !request.post? + render_status 405, "POST method required for action add_news" + return false + end + allowed = User.current.allowed_to?({:controller => 'news', :action => "new"}, @project) + if !allowed + msg = "No permission to add a news on project "+ @project.name + render_status 401, msg + else + @news = News.new(:project => @project, :author => User.current) + @news.attributes = news + if @news.save + Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added') + render_result @news + else + render_status 505, "Could not add the news..." + end + end + end + + def add_version_attachment + add_attachment + end + + def add_attachment(attachment = params["attachment"]) + if !request.post? + render_status 405, "POST method required for action add_attachment" + return false + end + container = !@version ? @project : @version + if attachment + file = attachment['file'] + next unless file && file.size > 0 + a = Attachment.create(:container => container, + :file => file, + :description => attachment['description'].to_s.strip, + :author => User.current) + end + if !attached.empty? && Setting.notified_events.include?('file_added') + array =[] + array << a + Mailer.deliver_attachments_added(array) + end + render_result a + end + + private + + def find_user + # Check the settings cache for each request + Setting.check_cache + # Find the current user + User.current = find_current_user + if !session[:user_id] + render_status 401, "Not connected" + end + end + + # Returns the current user or nil if no user is logged in + def find_current_user + if session[:user_id] + # existing session + (User.active.find(session[:user_id]) rescue nil) + elsif cookies[:autologin] + # auto-login feature + User.find_by_autologin_key(cookies[:autologin]) + end + end + + def find_project() + begin + @project = Project.find(params[:project_id]) + allowed = User.current.allowed_to?({:controller => 'jredmine', :action => "allow_jredmine"}, @project) + if !allowed + render_status 401, "No permission to access project nor jredmine service" + end + rescue ActiveRecord::RecordNotFound + render_status 404, "#{params[:project_id]} is not a project" + return false + end + end + + # recuperation des valeurs d'une enumration + def get_enumeration(type = params[:type]) + @result = Enumeration.get_values(type) + render_array_result @result, "enumerations" + end + + def check_edit + # check if user can edit the project + allowed = User.current.allowed_to?({:controller => 'projects', :action => "edit"}, @project) + if !allowed + render_status 401, "No permission to edit the project" + end + end + + def find_version(version = params[:version_name]) + @version = @project.versions.find_by_name(version) + if !@version + render_status 404, "#{version} is not a version for project #{@project.name}" + end + end + + def render_status(code,message) + render :text => message, :status => code + end + + def render_array_result(result,tag) + if !result.any? + respond_to do |format| + format.json { render :text => "[]" } + format.xml { render :text => "<"+tag+"></"+tag+">" } + end + else + respond_to do |format| + format.json { render :text => result.to_json } + format.xml { render :text => result.to_xml } + end + end + end + + def render_result(result) + respond_to do |format| + format.json { render :text => result.to_json } + format.xml { render :text => result.to_xml } + end + end + + def logged_user=(user) + if user && user.is_a?(User) + User.current = user + session[:user_id] = user.id + else + User.current = User.anonymous + session[:user_id] = nil + end + end + + def allowed_permissions + @allowed_permissions ||= begin + module_names = @project.enabled_modules.collect {|m| m.name} + Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name} + end + end + + def allowed_actions + @allowed_actions ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten + end + +end Property changes on: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/jredmine_controller.rb ___________________________________________________________________ Added: svn:mergeinfo + Deleted: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/rest_controller.rb =================================================================== --- jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/rest_controller.rb 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/redmine/jredmine/app/controllers/rest_controller.rb 2009-09-20 17:12:37 UTC (rev 189) @@ -1,352 +0,0 @@ -class RestController < ActionController::Base - - # find user (after login) - before_filter :find_user, :except => [:ping, :login] - - # find project and check permission - before_filter :find_project, :except => [:ping, :login, :logout, :get_projects, :get_issue_statuses, :get_issue_priorities] - - # find project's version - before_filter :find_version, :only => [:get_version, :get_version_issues, :get_version_attachments, :add_version_attachment] - - # check can edit project before push requests - #before_filter :check_edit, :only => [:add_version, :update_version, :add_file, :add_news, :add_attachment, :add_version_attachment] - - # ping service (just to test if service is reachable) - def ping - render :text => "ping", :status => 200 - end - - # Login request and validation - def login - if !request.post? - # Logout user : get method not possible - self.logged_user = nil - render_status 405, "POST method required" - else - # Authenticate user - user = User.try_to_login(params[:username], params[:password]) - if user.nil? - # Invalid credentials - render_status 401, "Invalid credentials" - elsif user.new_record? - # Onthefly creation failed, - render_status 401, "User not activated" - else - # Valid user - self.logged_user = user - # always generate a key and set autologin cookie - token = Token.create(:user => user, :action => 'autologin') - cookies[:autologin] = { :value => token.value, :expires => 1.year.from_now } - render_status 200, "User logged in" - end - end - end - - # Log out current user and redirect to welcome page - def logout - cookies.delete :autologin - Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? - # user is no more connected - self.logged_user = nil - render_status 200, "User logged out" - end - - # recuperation des projets - def get_projects - @projects = Project.find(:all) - render_array_result @projects, "projects" - end - - # recuperation des priorities d'issues - def get_issue_priorities - get_enumeration "IPRI" - end - - # recuperation des differentes categories d'issues - def get_issue_categories - @issue_categories = @project.issue_categories.find(:all) - render_array_result @issue_categories, "issue_categories" - end - - # recuperation des differentes statuts d'issues - def get_issue_statuses - @issue_status = IssueStatus.find(:all) - render_array_result @issue_status, "issue_statuses" - end - # recuperation du projet - def get_project - render_result @project - end - - # recuperation de tous les membres d'un projet - def get_project_users - @members = @project.members.find(:all) - @r = [] - for m in @members - u = User.find(m[:user_id]) - u[:role_id] = m[:role_id] - u[:member_id] = m[:id] - #TODO - should remove the hashed password ? - @r << u - end - render_array_result @r, "users" - end - - # recuperation de toutes les annonces d'un projet - def get_project_news - @news = @project.news.find(:all) - render_array_result @news, "news" - end - - # recuperation des trakers d'un projet - def get_project_trackers - @trackers = @project.trackers.find(:all) - render_array_result @trackers, "trackers" - end - - # recuperation des versions d'un projet - def get_project_versions - @versions = @project.versions.find(:all) - render_array_result @versions, "versions" - end - - # recuperation de la version d'un projet - def get_version - render_result @version - end - - # recuperation des issues d'un projet pour une version donnee - def get_version_issues - @issues = @version.fixed_issues.find(:all) - render_array_result @issues, "issues" - end - - # recuperation des pieces jointes d'un projet pour une version donnee - def get_version_attachments - @files = @version.attachments.find(:all) - render_array_result @files, "attachments" - end - - def show_permissions - allowed_permissions - render_result @allowed_permissions - end - - def show_actions - allowed_actions - render_result @allowed_actions - end - - # add a new version for a given project - def add_version(version=params[:version], description = params[:description], date = params[:date]) - if !request.post? - render_status 405, "POST method required for action add_version" - return false - end - @version = @project.versions.find_by_name(version) - if !@version - allowed = User.current.allowed_to?({:controller => 'projects', :action => "add_version"}, @project) - if !allowed - render_status 401, "No permission to add a version" - else - @version = Version.create(:project => @project, :name => version) - if description - @version['description'] = description - end - if date - @version['effective_date'] = date - end - if @version.save - render_result @version - else - render_status 505, "Could not add the version..." - end - end - else - render_result @version - end - end - - # update a existing version for a given project - def update_version(version=params[:version], description = params[:description], date = params[:date]) - if !request.post? - render_status 405, "POST method required for action update_version" - return false - end - @version = @project.versions.find_by_name(version) - if !@version - render_status 404, "The version " + version + " does not exist, can not update it..." - else - allowed = User.current.allowed_to?({:controller => 'versions', :action => "edit"}, @project) - if !allowed - render_status 401, "No permission to edit a version" - else - if description - @version['description'] = description - end - if date - @version['effective_date'] = date - end - if @version.save - render_result @version - else - render_status 505, "Could not update the version..." - end - end - end - end - - # add a new news for a given project - def add_news(author_id = params[:authorId]) - if !request.post? - render_status 405, "POST method required for action add_news" - return false - end - allowed = User.current.allowed_to?({:controller => 'news', :action => "new"}, @project) - if !allowed - msg = "No permission to add a news on project "+ @project.name - render_status 401, msg - else - news_user = User.find(author_id) - @news = News.new(:project => @project, :author => news_user) - @news.attributes = params[:news] - if @news.save - Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added') - render_result @news - else - render_status 505, "Could not add the news..." - end - end - end - - def add_version_attachment - add_attachment - end - - def add_attachment(attachment = params["attachment"]) - if !request.post? - render_status 405, "POST method required for action add_attachment" - return false - end - container = !@version ? @project : @version - if attachment - file = attachment['file'] - next unless file && file.size > 0 - a = Attachment.create(:container => container, - :file => file, - :description => attachment['description'].to_s.strip, - :author => User.current) - # a.new_record? ? (unsaved << a) : (attached << a) - # end - end - #if !attached.empty? && Setting.notified_events.include?('file_added') - # Mailer.deliver_attachments_added(attached) - #end - render_result a - end - - private - - def find_user - # Check the settings cache for each request - Setting.check_cache - # Find the current user - User.current = find_current_user - if !session[:user_id] - render_status 401, "Not connected" - end - end - - # Returns the current user or nil if no user is logged in - def find_current_user - if session[:user_id] - # existing session - (User.active.find(session[:user_id]) rescue nil) - elsif cookies[:autologin] - # auto-login feature - User.find_by_autologin_key(cookies[:autologin]) - end - end - - def find_project() - begin - @project = Project.find(params[:project_id]) - allowed = User.current.allowed_to?({:controller => 'rest', :action => "allow_rest"}, @project) - if !allowed - render_status 401, "No permission to access project nor rest service" - end - rescue ActiveRecord::RecordNotFound - render_status 404, "#{params[:project_id]} is not a project" - return false - end - end - - # recuperation des valeurs d'une enumration - def get_enumeration(type = params[:type]) - @result = Enumeration.get_values(type) - render_array_result @result, "enumerations" - end - - def check_edit - # check if user can edit the project - allowed = User.current.allowed_to?({:controller => 'projects', :action => "edit"}, @project) - if !allowed - render_status 401, "No permission to edit the project" - end - end - - def find_version(version = params[:version_name]) - @version = @project.versions.find_by_name(version) - if !@version - render_status 404, "#{version} is not a version for project #{@project.name}" - end - end - - def render_status(code,message) - render :text => message, :status => code - end - - def render_array_result(result,tag) - if !result.any? - respond_to do |format| - format.json { render :text => "[]" } - format.xml { render :text => "<"+tag+"></"+tag+">" } - end - else - respond_to do |format| - format.json { render :text => result.to_json } - format.xml { render :text => result.to_xml } - end - end - end - - def render_result(result) - respond_to do |format| - format.json { render :text => result.to_json } - format.xml { render :text => result.to_xml } - end - end - - def logged_user=(user) - if user && user.is_a?(User) - User.current = user - session[:user_id] = user.id - else - User.current = User.anonymous - session[:user_id] = nil - end - end - - def allowed_permissions - @allowed_permissions ||= begin - module_names = @project.enabled_modules.collect {|m| m.name} - Redmine::AccessControl.modules_permissions(module_names).collect {|p| p.name} - end - end - - def allowed_actions - @allowed_actions ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten - end - -end Modified: jredmine/trunk/jredmine-client/src/main/redmine/jredmine/init.rb =================================================================== --- jredmine/trunk/jredmine-client/src/main/redmine/jredmine/init.rb 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/main/redmine/jredmine/init.rb 2009-09-20 17:12:37 UTC (rev 189) @@ -1,11 +1,11 @@ require 'redmine' -Redmine::Plugin.register :redmine_rest do - name 'Redmine Rest plugin' +Redmine::Plugin.register :jredmine do + name 'JRedmine Rails plugin' author 'Tony Chemit' - description 'A plugin to expose projects in REST' + description 'A plugin to expose projects in REST protocol' version '0.0.1' - project_module :rest do - permission :allow_rest, :rest => :allow_rest + project_module :jredmine do + permission :allow_jredmine, :jredmine => :allow_jredmine end end Modified: jredmine/trunk/jredmine-client/src/site/apt/index.apt =================================================================== --- jredmine/trunk/jredmine-client/src/site/apt/index.apt 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/site/apt/index.apt 2009-09-20 17:12:37 UTC (rev 189) @@ -1,15 +1,124 @@ ---- -Introduction +JRedmine-client ---- ---- 2009-09-15 ---- -JRedmine model + Ce module contient un plugin <rails> qui permet d'ouvrir l'api de redmine au + protocole <REST>, ainsi q'un client <Java> pour interroger les services <REST>. - This module defines the java model mirroring the redmine model and offers - somme xml readers of redmine's datas in xml format using xpp3 xml parsers. +Plugin <rails> JRedmine + Le but de ce plugin est de pouvoir accéder aux données d'un serveur Redmine en + utilisant le protocole <REST>, mais aussi d'effectuer des tâches de + maintenance sur le serveur. + La page {{{rails_api.html}API}} détaille l'ensemble des services disponibles + depuis le serveur Redmine. +* Source du plugin + + Les sources du plugin <rails> sont sont dans le répertoire <<src/main/redmine>> + +-------------------------------------------------------------------------------- + +src/main/redmine/ +`-- jredmine + |-- README.rdoc + |-- app + | |-- controllers + | | `-- jredmine_controller.rb + | |-- helpers + | |-- models + | `-- views + |-- assets + | |-- images + | |-- javascripts + | `-- stylesheets + |-- db + | `-- migrate + |-- init.rb + |-- lang + | `-- en.yml + |-- lib + | `-- tasks + `-- test + `-- functional +-------------------------------------------------------------------------------- + +* Récupération d'une version packagée + + Il est possible de récupérer une version zippée du plugin (voir la section des + téléchargements). + +* Installation du plugin sur le serveur Redmine + + * récupération du zip du plugin + + * dézippage dans le répertoire vendor/plugins + + * ajouter au fichier <config/routes.rb> les lignes suivantes : + +-------------------------------------------------------------------------------- +# jredmine : ping, login , logout, with no project context... +map.connect 'jredmine/:action', :controller => 'jredmine' ,:action => ['ping',\ + 'login', 'logout', 'get_projects', 'get_issue_statuses', \ +'get_issue_priorities'] +map.connect 'jredmine/:action.:format', :controller => 'jredmine' ,:action => \ +['get_projects', 'get_issue_statuses', 'get_issue_priorities'], \ +:format => ['xml', 'json'] + +# jredmine/action/?? (:project_id) +map.connect 'jredmine/:action/:project_id', :controller => 'jredmine' +map.connect 'jredmine/:action.:format/:project_id', :controller => 'jredmine',\ +:format => ['xml', 'json'] +-------------------------------------------------------------------------------- + + * relancer votre instance de redmine (ou apache). + +* Configuration des permissions du plugin dans le serveur Redmine + + Le plugin est activable par projet et par rôle. + + Pour rendre accéssible le plugin pour un projet donné, il faut donc ajouter + le module JRedmine sur le projet dans l'onglet de configuration des modules + du projet. + + Pour rendre accéssible le plugin pour un rôle, il faut lui ajouter la + permission <<allow_jredmine>> dans la page des permissions du rôle. + +* Tester le plugin + + Une fois la configuration des permissions réalisées, vous pouvez tester le + plugin dans un navigateur web. + + Pour cela, loggez-vous en web sur redmine, puis lancer (dans un autre onglet) + l'url suivante : (remplacer <XX> par le chemin d'accès à votre redmine + et <YY> par le nom d'un de vos projet). + +-------------------------------------------------------------------------------- +http://XX/jredmine/get_project/YY +-------------------------------------------------------------------------------- + + Vous devez obtenir en retour la description xml du projet demandé. + +Client java + + Le client java qui interroge le plugin rails se base sur l'api du plugin rails + et transformer les données retournées en xml dans des objet java. + + La classe à utiliser est la suivante +-------------------------------------------------------------------------------- +org.nuiton.jredmine.DefaultRedmineService +-------------------------------------------------------------------------------- + + qui réalise le contrat + +-------------------------------------------------------------------------------- +org.nuiton.jredmine.RedmineService +-------------------------------------------------------------------------------- + + + <Pour plus de détails, consulter la javadoc du module.> \ No newline at end of file Added: jredmine/trunk/jredmine-client/src/site/apt/rails_api.apt =================================================================== --- jredmine/trunk/jredmine-client/src/site/apt/rails_api.apt (rev 0) +++ jredmine/trunk/jredmine-client/src/site/apt/rails_api.apt 2009-09-20 17:12:37 UTC (rev 189) @@ -0,0 +1,359 @@ +---- +API du plugin rails JRedmine +---- +---- +2009-09-20 +---- + +Introduction + + Ce document décrit l'API du plugin rails. + + + Toutes les actions REST sont préfixés par <<jredmine/>>. + + Par exemple, si votre serveur redmine accéssible sur <http://myredmine>, + les appels sur redmine seront de type <http://myredmine/jredmine/XXX>. + + On distingue donc trois types d'API : + + * API de login : pour gérer la connexion au serveur Redmine : une connexion + authentifié est requise pour pouvoir récupérer des données ou effectuer des + actions sur le serveur. + + * API de lecture : pour récupérer des données du serveur. + + * API d'actions : pour effecuter des actions de maintenance sur le serveur. + + Toutes les données en sortie du plugin sont au format <xml>, ou <json>. + +API de login + +*-----------*-----------------------------------------------+ +| <action> | <description> | +*-----------*-----------------------------------------------+ +| <<ping>> | un service de ping qui retourne le mot <ping> | +*-----------*-----------------------------------------------+ +| <<login>> | pour connecter l'utilisateur au serveur | +*-----------*-----------------------------------------------+ +| <<logout>>| pour déconnecter l'utilisateur du serveur | +*-----------*-----------------------------------------------+ + +* ping + + Ce service ne requiert pas de paramètre. + + Requète : + +-------------------------------------------------------------------------------- +jredmine/ping +-------------------------------------------------------------------------------- + +* login + + Ce service nécessite deux paramètres : + + * <<username>> + + * <<password>> + + <<Note:>> Cette requête ne peut être exécutée qu'en <<POST>>. + + Requète : + +-------------------------------------------------------------------------------- +jredmine/login +-------------------------------------------------------------------------------- + +* logout + + Ce service ne requiert pas de paramètre. + + Requète : + +-------------------------------------------------------------------------------- +jredmine/logout +-------------------------------------------------------------------------------- + +API de lecture + + On distingue trois niveaux de données récupérables : + + * les données qui ne dépendent pas d'un projet + + * les données qui dépendent d'un projet + + * les données qui dépendent d'une version d'un projet + +* Services des données indépendantes + +*--------------------------*-----------------------------------+ +| <action[.xml\|.json]> | <données récupérées> | +*--------------------------*-----------------------------------+ +| <<get_projects>> | tous les projets | +*--------------------------*-----------------------------------+ +| <<get_issue_statuses>> | tous les status de demandes | +*--------------------------*-----------------------------------+ +| <<get_issue_priorities>> | toutes les prioritiés de demandes | +*--------------------------*-----------------------------------+ + +** get_projects + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_projects.xml +jredmine/get_projects.json +-------------------------------------------------------------------------------- + +** get_issue_statuses + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_issue_statuses.xml +jredmine/get_issue_statuses.json +-------------------------------------------------------------------------------- + +** get_issue_priorities + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_issue_priorities.xml +jredmine/get_issue_priorities.json +-------------------------------------------------------------------------------- + +* Services des données dépendantes d'un projet + +*--------------------------*---------------------------------------+ +| <action[.xml\|.json]> | <données récupérées pour un projet> | +*--------------------------*---------------------------------------+ +| <<get_projet>> | le projet | +*--------------------------*---------------------------------------+ +| <<get_issue_categories>> | touts les catégories de demande | +*--------------------------*---------------------------------------+ +| <<get_project_users>> | tous les membres du projet | +*--------------------------*---------------------------------------+ +| <<get_project_trackers>> | tous les types de tracker | +*--------------------------*---------------------------------------+ +| <<get_project_versions>> | toutes les versions d'un projet | +*--------------------------*---------------------------------------+ + +** get_projet + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_projet.xml/myProject +jredmine/get_projet.json/myProject +-------------------------------------------------------------------------------- + +** get_issue_categories + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_issue_categories.xml/myProject +jredmine/get_issue_categories.json/myProject +-------------------------------------------------------------------------------- + +** get_project_users + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_project_users.xml/myProject +jredmine/get_project_users.json/myProject +-------------------------------------------------------------------------------- + +** get_project_trackers + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_project_trackers.xml/myProject +jredmine/get_project_trackers.json/myProject +-------------------------------------------------------------------------------- + +** get_project_versions + + Ce service ne requiert pas de paramètre. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_project_versions.xml/myProject +jredmine/get_project_versions.json/myProject +-------------------------------------------------------------------------------- + +* Services des données dépendantes d'une version d'un projet + +*------------------------------*-----------------------------------------------------+ +| <action[.xml\|.json]> | <données récupérées pour une version d'un projet> | +*------------------------------*-----------------------------------------------------+ +| <<get_version>> | la version | +*------------------------------*-----------------------------------------------------+ +| <<get_version_issues>> | touts les catégories de demande | +*------------------------------*-----------------------------------------------------+ +| <<get_versions_attachments>> | tous les membres du projet | +*------------------------------*-----------------------------------------------------+ + +** get_version + + Ce service requiert un paramètre : + + * <<version_name>> le nom de la version + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_version.xml/myProject?version_name=myVersion +jredmine/get_version.json/myProject?version_name=myVersion +-------------------------------------------------------------------------------- + +** get_version_issues + + Ce service requiert un paramètre : + + * <<version_name>> le nom de la version + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_version_issues.xml/myProject?version_name=myVersion +jredmine/get_version_issues.json/myProject?version_name=myVersion +-------------------------------------------------------------------------------- + +** get_versions_attachments + + Ce service requiert un paramètre : + + * <<version_name>> le nom de la version + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/get_versions_attachments.xml/myProject?version_name=myVersion +jredmine/get_versions_attachments.json/myProject?version_name=myVersion +-------------------------------------------------------------------------------- + +API d'actions + +*----------------------------*----------------------------------------------+ +| <action> | <description> | +*----------------------------*----------------------------------------------+ +| <<add_version>> | ajouter une version à un projet | +*----------------------------*----------------------------------------------+ +| <<update_version>> | mettre à jour une version d'un projet | +*----------------------------*----------------------------------------------+ +| <<add_attachment>> | ajouter un fichier à un projet | +*----------------------------*----------------------------------------------+ +| <<add_version_attachment>> | ajouter un fichier à une version d'un projet | +*----------------------------*----------------------------------------------+ +| <<add_news>> | ajouter une annonce à un projet | +*----------------------------*----------------------------------------------+ + + <<Note:>> Toutes ces opérations doivent obligatoirement être exécutées + par une méthod http <<POST>> (donc pas réalisable via un navigateur). + +* add_version + + Ce service requiert trois paramètres : + + * <<version[name]>> le nom de la version + + * <<version[description]>> la description de la version + + * <<version[effective_date]>> la date effective de la version + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/add_version.xml/myProject +jredmine/add_version.json/myProject +-------------------------------------------------------------------------------- + +* update_version + + Ce service requiert trois paramètres : + + * <<version[name]>> le nom de la version + + * <<version[description]>> la description de la version + + * <<version[effective_date]>> la date effective de la version + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/update_version.xml/myProject +jredmine/update_version.json/myProject +-------------------------------------------------------------------------------- + +* add_attachment + + Ce service requiert deux paramètres : + + * <<attachment[description]>> la description de la pièce jointe + + * <<attachment[file]>> la pièce-jointe + + <<Note:>> La requète est de type <<multi-part>>. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/add_attachment.xml/myProject +jredmine/add_attachment.json/myProject +-------------------------------------------------------------------------------- + +* add_version_attachment + + Ce service requiert trois paramètres : + + * <<version_name>> le nom de la version + + * <<attachment[description]>> la description de la pièce jointe + + * <<attachment[file]>> la pièce-jointe + + <<Note:>> La requète est de type <<multi-part>>. + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/add_version_attachment.xml/myProject +jredmine/add_version_attachment.json/myProject +-------------------------------------------------------------------------------- + +* add_news + + Ce service requiert trois paramètres : + + * <<news[title]>> le titre de de la version + + * <<news[summary]>> la description de l'annonce + + * <<news[description]>> le contenu de l'annonce + + Requètes : + +-------------------------------------------------------------------------------- +jredmine/add_news.xml/myProject +jredmine/add_news.json/myProject +-------------------------------------------------------------------------------- Modified: jredmine/trunk/jredmine-client/src/site/site.xml =================================================================== --- jredmine/trunk/jredmine-client/src/site/site.xml 2009-09-19 18:28:30 UTC (rev 188) +++ jredmine/trunk/jredmine-client/src/site/site.xml 2009-09-20 17:12:37 UTC (rev 189) @@ -14,6 +14,7 @@ <menu name="Utilisateur"> <item name="Introduction" href="index.html"/> + <item name="JRedmine rails API" href="rails_api.html"/> <!--item name="Usage" href="usage.html"/> <item name="Goals" href="plugin-info.html"> <item name="generate-changes" href="generate-changes-mojo.html"/>