developer_manual
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
developer_manual [2018/10/22 03:01] – [Data Collection Workbook] ghachey | developer_manual [2020/03/23 08:27] (current) – removed ghachey | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Pacific EMIS Developer Guide ====== | ||
- | |||
- | ===== Introduction ===== | ||
- | |||
- | The Pacific Education Management Information System (Pacific EMIS) is an open source application developed to improve the education system in Pacific nations. It is currently being developed and supported by the Secretariat of the Pacific Community (SPC) with support from the Asia Development Bank (ADB). This guide is for any developers | ||
- | |||
- | ==== Project Overview ==== | ||
- | |||
- | The Pacific EMIS is a single page web application built with AngularJS and ASP.NET technologies. While it is important to know that this web application is complementary to a desktop application in some countries, built on the same database, that was first started in 2002. So there is a lot of functionality in there that hasn't been ported to the web version; we've concentrated so far on the features of most use to a broader user base. For example, lookup table maintenance is done (when needed) through the desktop because there hasn't been a lot to be gained by porting that. This developer guide is mostly gear towards the Web application only (which again, make use of the same database as the legacy desktop application). The web application project moving forward is likely to eventually obsolete the legacy MS Access desktop application completely. | ||
- | |||
- | ==== Project Structure ==== | ||
- | |||
- | The Pineapples solution (in Visual Studio parlance) is managed in a single git repository. The solution is organised into 3 main projects (which also translates into three folders in the root of the repository): | ||
- | |||
- | * **Pineapples** ASP.NET project: This is the startup executable. It is responsible for delivering all objects to the browser, including the initial page, all required scripts, stylesheets, | ||
- | |||
- | * **Pineapples.Data** .NET class library: This project exposes " | ||
- | * **Pineapples.Client** .NET Web Site. The client front-end (i.e. javascript and css files executed in the browser). As a web site, this project has no project file, and Visual Studio build is turned off. The project is managed using a "web stack" composed of npm, bower and grunt. | ||
- | |||
- | Two other projects complete the solution: | ||
- | |||
- | * **Pineappples.Reports**: | ||
- | * **Pineapples.Data.Tests**: | ||
- | * **JaspersoftWorkspace**: | ||
- | |||
- | Other folders found in the root of the git repository are: | ||
- | |||
- | * **assemblies**: | ||
- | * **database**: | ||
- | * **packages**: | ||
- | * **SqlScript**: | ||
- | |||
- | ==== Programming Language ==== | ||
- | |||
- | The programming language on the backend (i.e. Pineapples, Pineapples.Data, | ||
- | |||
- | Why not ASP.NET5 and Angular 2? The short answer, those two projects were not in stable release when this project started. Moving to any of those is not an upgrade but potentially a significant rewrite. New code is written in as to ease the transition down the line. This will be reviewed in mid 2017. | ||
- | |||
- | Things to consider regarding ASP.NET4.6 to ASP.NET5 migration path. | ||
- | |||
- | ^ Issue ^ Pineapples (ASP.NET4.6) ^ ASP.NET5 ^ | ||
- | |Separation of client-side SPA from server logic. | Separation into 3 projects. Pineapples.Client Web site is all the client material and npm/bower depencies. Managed entirely by grunt. | Adds wwwroot and dependencies folders into project for this purpose. | | ||
- | |Data Access | Microsoft' | ||
- | | Dependency Injection | Unity framework has adaptor for Web Api. These are used in Pineapples. | Dependency injection built in to ASP.NET5 | | ||
- | | Confusion between Web API controllers and MVC controllers. | Separated into two folders: Controllers and Controllers_Api. Use specific base custom classes. | Merges Web API into MVC. Only one type of control | | ||
- | |||
- | Similar considerations around Angular 1 vs 2. This is a rewrite, but tools are being introduced into 1 (see Angular 1.5) to ease this path. Adhering to best practices will make the transition smoother down the track: | ||
- | |||
- | * Angular 2 is entirely written in Typescript, so should new Pineapples code. | ||
- | * Try not to use scope (store variables on controller not on scope). Refer to source code for example of how this works. | ||
- | * Move to Angular 1.5 components where possible rather than lower level directives. | ||
- | |||
- | |||
- | ==== Development Web Stack ==== | ||
- | |||
- | No web application is built without a web framework (or library). As was mentioned previously the frameworks used are ASP.NET4.6 and Angular 1. In addition to the frameworks used for the development of the application itself a modern web stack is also used to manage various aspects of the frontend development (i.e. Pineapples.Client) such as running tests and building the frontend part of the application: | ||
- | |||
- | * [[https:// | ||
- | |||
- | * [[https:// | ||
- | |||
- | * [[http:// | ||
- | |||
- | * [[http:// | ||
- | |||
- | ==== Database and Operating System ==== | ||
- | |||
- | Only Microsoft SQL Server is supported. However, the application only requires the freely available [[http:// | ||
- | |||
- | Currently the application is developed on windows and must be deployed on Windows; any recent version of windows, preferably though not necessarily Windows server. | ||
- | ===== Setting Up the Development Environment ===== | ||
- | |||
- | The easiest way to get a development environment and start developing on the Pacific EMIS is on Windows with instructions below. | ||
- | |||
- | ==== Main Development Tools ==== | ||
- | |||
- | Most developers currently use Visual Studio, ASP.NET4.6 (comes with Visual Studio), MS SQL Server Express or Developer Edition, IIS, NodeJS/NPM and SourceTree/ | ||
- | |||
- | - Download and install latest [[https:// | ||
- | - Download and install [[http:// | ||
- | - Enable IIS feature | ||
- | - Download and install [[https:// | ||
- | - Install Bower from the command line you can simply ''> | ||
- | - Install Grunt from the command line you can simply ''> | ||
- | - You will also need to download and install [[https:// | ||
- | |||
- | ==== Software Configuration Management ==== | ||
- | |||
- | All software is managed through Git (Version Control Management) and currently Bitbucket (Issue tracking, collaboration, | ||
- | |||
- | **In SourceTree** | ||
- | |||
- | Create the folder '' | ||
- | |||
- | In short, your cloning in SourceTree could look something like the following. It is better to checkout **develop** as this is where the stable source code leaves. Once you get this working on **develop** then you can start creating branches for to develop new code. | ||
- | |||
- | {{ : | ||
- | |||
- | **Git command line** | ||
- | |||
- | < | ||
- | > cd C:\ | ||
- | > git clone https:// | ||
- | </ | ||
- | |||
- | <note important> | ||
- | The reason why examples above put the code in C: | ||
- | </ | ||
- | |||
- | ==== Visual Studio Setup ==== | ||
- | |||
- | Start VS and click on **Open - Project/ | ||
- | |||
- | Before you attempt to build the solution there are two things that will help avoid annoying errors/ | ||
- | |||
- | === Update SQL Server Data Tools in Visual Studio 2015 === | ||
- | |||
- | Essentially, | ||
- | |||
- | === Make sure Visual Studio uses your latest install NodeJS/NPM === | ||
- | |||
- | If you already have it installed as instructed above you can now click **Tools - Options** and try to make sure that VS searches on the PATH of windows first so that the newly installed NodeJS/NPM take precedence other external web tools (e.g. bower, npm, grunt). | ||
- | |||
- | {{ : | ||
- | |||
- | You can then verify if VS is actually using the node and npm binaries you think they were by opening **Tools - NuGet Package Manager - Package Manager Console** and typing the following commands and observing the output. | ||
- | |||
- | {{ : | ||
- | |||
- | |||
- | ==== Databases Setup ==== | ||
- | |||
- | You will need to setup two databases: the application' | ||
- | |||
- | Restoring a database from a backup is documented [[https:// | ||
- | |||
- | In VS, open the file '' | ||
- | |||
- | <code xml> | ||
- | <add name=" | ||
- | </ | ||
- | |||
- | And replace '' | ||
- | |||
- | <code xml> | ||
- | < | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | </ | ||
- | </ | ||
- | |||
- | And replace '' | ||
- | |||
- | ==== Building the Solution ==== | ||
- | |||
- | First, as a one time thing, you need to set the starting project of the solution. Right click on the **Pineapples** project in the **Solution Explorer** and click on **Set as StartUp project**. The Pineapples project should from now on become bold. | ||
- | |||
- | At this point if you followed closely the previous sections you should already be able to right click on the **Solution ' | ||
- | |||
- | To then run the system you can click on the following. Note that below was first set to Google Chrome but it could be started within any browser. | ||
- | |||
- | {{ : | ||
- | |||
- | <note tip> | ||
- | |||
- | === Verifying Dependencies === | ||
- | |||
- | Make sure all projects have their dependencies sorted. Start with **Pineapples.Data** project. Ensure that the references to **Softwords.Datatools**, | ||
- | |||
- | {{ : | ||
- | |||
- | Ensure all references are present. Build **Pineapples.Data**, | ||
- | |||
- | {{ : | ||
- | |||
- | Check in particular that reference to **Microsoft.Practices.Unity** are resolved. These come from Nuget and should be available. Build the project **Pineapples**, | ||
- | |||
- | ==== JasperSoft Studio Setup ==== | ||
- | |||
- | Most of the reports are done in JasperReports, | ||
- | |||
- | Once installed on the computer the developer should familiarize with the comprehensive user documentation for JasperReports which is available at the same place. After successfully installing JasperSoft Studio and running some basic reports from the user documentation you should be ready to run the Pacific EMIS reports. | ||
- | |||
- | You can access all reports for each adopting country (e.g.FEDEMIS, | ||
- | |||
- | {{ : | ||
- | |||
- | This should automatically get you all the Pacific EMIS reports for all adopting countries right into your reporting development environment. | ||
- | |||
- | Next you will need to make sure you have a database driver capable of talking to the MS SQL Server. This can be downloaded [[https:// | ||
- | |||
- | {{ : | ||
- | |||
- | TODO | ||
- | |||
- | * Create the datasource for one database (same for others) | ||
- | * Open an example report and run it | ||
- | * Discuss standards to follow (all reports should be mostly replicated across all adopting countries, custom styling per countries, etc.) | ||
- | |||
- | |||
- | ===== Development Work-flow ===== | ||
- | |||
- | The Pacific EMIS project constantly strives to improve its development operations in order to produce software of higher quality at a more efficient rate. This part of the developer guide will undoubtably change and should be kept close at hand when developing on this project. | ||
- | |||
- | ==== Frontend Development Tools ==== | ||
- | |||
- | The application is tested using the Chrome web browser which has good developer tools out of the box. For more advanced debugging of the frontend the developers mostly use [[http:// | ||
- | |||
- | {{ : | ||
- | |||
- | To eliminate all the noise of using fiddler as a proxy you can filter to only show connections to specific hosts, in our case we will include the two default hosts that VS will run the development version of the web application using the IIS express web server. That is, hosts localhost: | ||
- | |||
- | {{ : | ||
- | |||
- | Since we are developing an application that runs through HTTPS encrypted channel it is useful to decrypt this traffic in fiddler so it can actually be examined and used for troubleshooting and development. Click Fiddler' | ||
- | |||
- | {{ : | ||
- | |||
- | This should you started with this very useful in analyzing all your web application traffic. | ||
- | ==== Contributing Code General Workflow ==== | ||
- | |||
- | In general all contributions by third parties should be done through forking the public repository, creating a local branch to work on based on the issue that is assigned to you, creating a pull request back to the original repository. | ||
- | |||
- | === Forking the Public Repository === | ||
- | |||
- | To fork you must first be logged on your Bitbucket repository. Point the browser to the https:// | ||
- | |||
- | {{ : | ||
- | |||
- | Then Fork this repository as below. | ||
- | |||
- | {{ : | ||
- | |||
- | Then fork with the following settings. | ||
- | |||
- | {{ : | ||
- | |||
- | You should see it now under your own username as shown underlined below. Make sure you have SourceTree installed and click clone in SourceTree. | ||
- | |||
- | {{ : | ||
- | |||
- | You should checkout the branch develop as below. | ||
- | |||
- | {{ : | ||
- | |||
- | You are now ready to start working on your own copy of the pineapples repository. More on forking with bitbucket can be found at https:// | ||
- | |||
- | === Creating Branch on your New Local Repository === | ||
- | |||
- | Our normal process is we have issues in the issue tracking system. Contributors are typically assigned issues as shown below. | ||
- | |||
- | {{ : | ||
- | |||
- | In that example, Brian Lewis would create a branch called issue354 and work on that for that particular issue (e.g. a bug fix, a new feature, etc.) | ||
- | |||
- | === Creating a Pull Request back to Original Repository === | ||
- | |||
- | Before you can create a pull request back into original repository there are 2 things you need to prepare. | ||
- | |||
- | 1) The original repository may have evolved. You would need to pull that inside your own stuff to make yourself in sync again. You are responsible for that. | ||
- | |||
- | 2) Once in sync you need to consolidate your PR into a single commit with a commit message following our standard. Refer to the section below " | ||
- | |||
- | The core developers can help with this preparation if you are not an experience Git user. | ||
- | |||
- | Once your new shinny work is ready to go back to the original pineapples repository you can create your pull request. | ||
- | |||
- | TODO Screenshot how to do this. | ||
- | |||
- | More on creating a pull request with bitbucket is available at https:// | ||
- | |||
- | |||
- | |||
- | ==== Database Schema Changes ==== | ||
- | |||
- | Database schema migration are currently done more or less manually with the help of a proprietary tool called SQLDelta. Currently there is only the most current schema available and it is not easy to revert to older schemas from previous releases. So it is important to stay up-to-date. The database schema of the developer can be made up-to-date by syncing with the master reference database | ||
- | |||
- | FIXME - Include steps and a simple schema upgrade with screenshots | ||
- | |||
- | Note that when you make schema changes, you should run the SP " | ||
- | |||
- | |||
- | ==== Testing Code ==== | ||
- | |||
- | Currently not a lot of test is being done, but eventually all new branches doing into '' | ||
- | |||
- | FIXME develop this section further as we move forward. Here are some notes to get started: | ||
- | |||
- | * karma test infrastructure is in place in the grunt file. unit test are added into the test folder. Ad-hoc test pages can be stored in testpages. these can be run in IIS Express, which is started with the grunt task iisexpress: | ||
- | |||
- | * establish and start to enforce lint standards in the typescript and javascript code (and hopefully in c# somehow) | ||
- | |||
- | * move to a test-driven methodology, | ||
- | |||
- | ===== High Level Architecture ===== | ||
- | |||
- | <note warning> | ||
- | |||
- | To recap what was already introduced in [[# | ||
- | |||
- | {{ : | ||
- | |||
- | ==== Data Retrieval Service ==== | ||
- | |||
- | The architecture of the data retrieval service is shown below. | ||
- | |||
- | {{ : | ||
- | |||
- | And here is a short discussion regarding the use of Entity Framework 6 vs. ADO.NET by the project main software architect, Brian Lewis. | ||
- | |||
- | | I did have a look at that some time back and ended up rolling back, | ||
- | | thinking the time is not right. I'm more inclined to wait for EF7 to | ||
- | | mature, rather than adopt 6 now and have to deal with another | ||
- | | conversion. But – noting the earlier observation that simple CRUD | ||
- | | operations on lookups and master tables are not yet in Pineapples | ||
- | | and a standalone implementation will need them, I can see benefits | ||
- | | in the medium term. | ||
- | | | ||
- | | To dig a bit deeper, although most of the data access is done | ||
- | | through ADO.Net connections and command manipulation, | ||
- | | that connection object comes from a linqToSql class – an earlier | ||
- | | .NET ORM . It exposes a ADO.NET connection and that is what is | ||
- | | used. But in one or two places it does use LinqToSQl – see | ||
- | | PDBPerfAsess.cs – and not coincidentally, | ||
- | | currently trying to do simple record level writing. | ||
- | | | ||
- | | So the path to EF7 would probably begin with replacing that | ||
- | | linqToSql context with an EF7 DBContext, then digging the ADO.NET | ||
- | | connection out of that to use in all the existing ADO.NET code: See | ||
- | | [[http:// | ||
- | | shows how to get that low-level connection object out of the EF7 | ||
- | | wrapper. In fact there' | ||
- | | Pineapples.Data (doing nothing.) | ||
- | | | ||
- | | While I'm generally on board with strongly-typing (hence moving js | ||
- | | -> typescript) bear in mind that you do get a bit of overhead with | ||
- | | EF in that you need a class to represent the result set of a | ||
- | | query. When reading, this class only exists to get turned into JSON | ||
- | | – and you'd get the same JSON serialising an ADO.NET | ||
- | | DataTable. However, serialising a DataTable means that you can | ||
- | | change the query and everything still works without a | ||
- | | recompile. This is especially useful in the circumstance where we | ||
- | | have Stored Procs that can return a variety of record shapes driven | ||
- | | by the "view mode": | ||
- | | | ||
- | | The " | ||
- | | figure below winds its way right down to the stored proc. This type | ||
- | | of thing is pretty painful in a strongly typed ORM, but simple when | ||
- | | working with DataTables. | ||
- | |||
- | {{ : | ||
- | | ||
- | ==== Templates ==== | ||
- | |||
- | The architecture of templates is shown below. | ||
- | |||
- | {{ : | ||
- | |||
- | ==== Theme (Look and Feel) ==== | ||
- | |||
- | Currently a little messy. Started out with a paid theme based on bootstrap now a lot of it is out and just building with HTML and CSS "left overs" from the theme. The current idea on the road map would be to move to a full Angular Material based interface to provide a professional consistent UI. | ||
- | |||
- | ==== Navigation and Module System ==== | ||
- | |||
- | The Navigation menu in the side bar is loaded when the user logs in. | ||
- | |||
- | {{ : | ||
- | |||
- | It is part of the packet of data returned with the BearerToken in response to api/token. | ||
- | |||
- | {{ : | ||
- | |||
- | Both the menu and the '' | ||
- | |||
- | |||
- | {{ : | ||
- | |||
- | There are 3 types of entries in the IdentitiesP' | ||
- | |||
- | * Those like ALL, which represent a menu that may be assigned to a user | ||
- | * Submenus, that are parents of a collection of function (e.g. schools) | ||
- | * End points that are a specific system function (e.g. schools.list) | ||
- | |||
- | And is a brief description of its columns | ||
- | |||
- | * **Icon**: this is fontawesome coding for the icon to show on that menu. | ||
- | * **Label**: text for the menu item | ||
- | * **State**: for functions, this is the ui-router state to go to when that function is selected. Obviously, these need to be defined in the Javascript/ | ||
- | * **Children**: | ||
- | * **homestate**: | ||
- | |||
- | Roles are sent to the client. For ASP.NET users, these come from the IdentitiesP database. For domain users, it is just currently a list of ActiveDirectory groups. A role can be associated to a ui-route on the client. Access to that route can be dependent on belonging to the Role. (Note that even if a route is not exposed through the menu, you can still navigate to it if you know its URL.) This is managed by the component *angular-permission*. | ||
- | |||
- | Also sent to the client are *Filters*. These are restrictions on what a user may select in the searcher pages. For example, a filter of *District=DC* will mean that the Province dropdowns will be locked to province *DC* (note that this is ultimately enforced on the server based on the bearer token.) | ||
- | |||
- | {{ : | ||
- | |||
- | Menu filter and roles are sent to the client at login, but are also encapsulated as Roles and Claims in the bearer token. Their use on the client is more a courtesy than a security feature: on the client, we don’t show the user things that they will not be able to do on the server, where the Claim is enforced based on the token. | ||
- | |||
- | FIXME We need to better integrate the Roles, Filters and menu that are retrieved for a user who authenticates against Active Directory. This is important in Solomon Islands for example, where we will need to distinguish between users logging in to the the government domain. Brian suggest that this will be some data-driven mapping between Active Directory groups, and some abstract ASP.NET Identity account representing that group. So at login, if you are identified as belonging to some specified AD group, you will get the MenuKey, Filters and Roles associated to that group. | ||
- | |||
- | |||
- | ==== Lookups and Configuration ==== | ||
- | |||
- | The Pacific EMIS is mainly configured and adapted to different countries through lookups in the database. Along side this document is kept a spreadsheet called [[/ | ||
- | |||
- | ==== Note on Report Parameters ==== | ||
- | |||
- | While JasperServer is where the reports are stored and run they can be accessed through a RESTful API. The Pacific EMIS can automatically integrate all published reports in a JasperServer for a professional unified UI design. The way this works in Pacific online is that the Context you are running the report in (e.g. from an individual school) will supply report parameters with specific names if they are required. For eample, from the new Reports tab within a particular School it will try to push a parameter ‘SchoolNo’ containing the current school’s ID instead of the user having to manually enter the SchoolNo for which the report is sought. | ||
- | |||
- | If there are any parameters required that are not supplied, you’ll get a dialog to prompt for all parameters, with any that can be supplied already filled in. So on this basis, if your reports use other parameter names, they will still run in Pacific EMIS, but you will have to key in the parameters (just as you would in Jasper server); you won’t get them supplied. | ||
- | |||
- | The dialog displayed in Pacific EMIS Online will also respect any dropdown list associated with a Jasper Input Control attached to the report. So the aim is to have a collection of such input controls and queries set up in common in all our Jasper installations. In fact these will be the same queries and names as used in the Lookups within Pacific EMIS Online. | ||
- | |||
- | ===== Technology Documentation ===== | ||
- | |||
- | Various approaches and tools used by the developers of this project are documented here. | ||
- | |||
- | ==== Object to Relational Data Mapping ==== | ||
- | |||
- | Originally pineapples made us of Linq2SQL but has since moved to EF6. Key differences in moving to Entity Framework from Linq2Sql: | ||
- | |||
- | L2S use the custom dbml designer to build its model of the database. EF uses explicit, and simpler, classes: | ||
- | |||
- | * context class - the overarching data " | ||
- | * entity classes - one class for each entity , correspond to database tables basically. These classes are now in Pineapples.Data.Models; | ||
- | |||
- | The context class contains a collection property for each entity e.g. cxt.Books. While called ' | ||
- | |||
- | We use this tool [[https:// | ||
- | |||
- | It generates everything we need it to do, its failing is that it can be quite slow on a big database (parsing the entire database, including all stored procs, on load). However, it has a command line mode which is probably all we'll ever need. While there is a Visual Studio addin that works with the templating infrastructure (TT) it was found that the simpler approach was to use the POCO tool directly and copy code to VS. | ||
- | |||
- | Once installed you can use options as shown in the following figure as starting point. | ||
- | |||
- | {{ : | ||
- | |||
- | The equivalent command line would be this if you prefer: | ||
- | |||
- | {{ : | ||
- | |||
- | < | ||
- | Note that the " | ||
- | |||
- | The Binders also make use of some custom Attributes that were added " | ||
- | |||
- | To get all the pCreateUser, | ||
- | </ | ||
- | |||
- | ==== Kobo Framework Data Collection ==== | ||
- | |||
- | This feature allows custom school inspections to be implemented as Kobo Toolbox forms, and loaded into SIEMIS. Of course, this facility can apply to any Pacific EMIS installation, | ||
- | |||
- | === Set Up === | ||
- | |||
- | First step in Set up is to create in SIEMIS a School Inspection Type to represent the custom inspection type. This can be done either using the Admin function in desktop SIEMIS, or the new /tables maintenance functions in Pacific EMIS. Next, design the form in Kobo toolbox. There are just four requirements: | ||
- | |||
- | === Loading === | ||
- | |||
- | A form meeting this design can be loaded into SIEMIS using the kobo/upload page. First, download the form data from Kobo as an Excel file. IMPORTANT: The Kobo Excel file as downloaded has a slightly non-standard format, so open it in Excel and immediately save it to straighten this out. You may also review the downloaded Excel and make any corrections you think necessary. When you load the file into SIEMIS, the uploader writes a new school inspection record of the custom type for each school. The date of the inspection is taken from the Kobo start and end fields (present in every Kobo survey). The custom fields in your survey are stored as a single Xml “blob” on the inspection record. | ||
- | |||
- | === Reporting === | ||
- | |||
- | To report on the inspection type, create a new view in the SIEMIS database with the name pInspectionRead.< | ||
- | |||
- | <code sql> | ||
- | ALTER VIEW [pInspectionRead].[ENVER] | ||
- | WITH VIEW_METADATA | ||
- | AS | ||
- | Select S.* | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | , S.extraData.value(' | ||
- | |||
- | FROM pInspectionRead.SchoolInspections S | ||
- | WHERE S.InspTypeCode = ' | ||
- | GO | ||
- | </ | ||
- | |||
- | Here the M0, F0, C0 etc fields correspond to the custom field names created in the Kobo designer. extraData in this view represents the Xml blob; the value function extract the fields by name. The second part of the value function specifies the data type of the extracted value – use int for whole numbers, nvarchar(50) for text, float (or decima) for numbers that may contain fractions. These same names are used for the resulting columns in the output, as shown here: | ||
- | |||
- | This data could be used to source a Jasper report, a pivot table, or other reporting output. Further the stored procedure pinspectionRead.ReadInspection < | ||
- | |||
- | This could be built upon in future development to allow custom user interface by inspection type within Pacific EMIS. | ||
- | |||
- | ==== Reporting Framework ==== | ||
- | |||
- | While the system can potentially support JasperReports, | ||
- | |||
- | The JasperServer supports a comprehensive RESTful API for integration with other systems and this is what is used by the Pacific EMIS to include professional reports directly into the Pacific EMIS web UI. | ||
- | |||
- | Integration provides: | ||
- | |||
- | * A single page listing all KEMIS reports in the Jasper server | ||
- | * A page listing that subset of reports relating to a particular entity (e.g. Schools, Teachers) | ||
- | * A tab on Entities showing reports relating to a single item (e.g. a school, a teacher) | ||
- | * Opportunities to embed reports at context-specific places in the user interface. In other words, including any report anywhere. | ||
- | |||
- | === Jasper Technologies Installation === | ||
- | |||
- | A developer wanting to work with this would need to: | ||
- | |||
- | * Install the [[https:// | ||
- | * Install the [[JasperReports Server|https:// | ||
- | * Optionally install the [[JasperReports Server|https:// | ||
- | * Provide appropriate security for JasperReports Server (i.e. change default username and password at minimum) at least for production development. | ||
- | |||
- | === Jasper Technologies Configuration === | ||
- | |||
- | Assuming you have already cloned the software repository and installed Jasper as in previous step you are almost ready to get started. The first thing to do is to set your Jaspersoft Studio Workspace to point to the location where all the reports for this project are located. For example, the docs clone the software repository into the '' | ||
- | |||
- | {{ : | ||
- | |||
- | Second thing, since we are using the MS SQL Server database we will need to install the [[https:// | ||
- | |||
- | {{ : | ||
- | |||
- | === Reports Structure === | ||
- | |||
- | For things to work as designed and expected you will need to follow some simple convention for how you structure your reports. Basically, it should reflect what is shown in the following illustration. That is in MyReports we have a list of country context all in small caps (e.g. fedemis, miemis, siemis, kemis, etc.). Each of those countries have a list of EMIS modules (e.g. Exams, Schools, Teachers, Students, etc.). Those EMIS modules have reports relevant their their respective modules. For example, Schools, contain schools reports. Then each module can potentially have EMIS module instances (e.g. a School, a Teacher, etc.) Those contain reports for individual instances (e.g. a school card report, a teacher profile report). Other reports can for now be organized in any way but may need to be included manually in the UI as oppose to automatically listed in their respective locations. Images and Templates folder simply contain reusable resources like logo and " | ||
- | |||
- | {{ : | ||
- | |||
- | === Running and Deploying Reports === | ||
- | |||
- | TODO | ||
- | |||
- | === Report Parameters === | ||
- | |||
- | The EMIS will attempt to provide the parameters to the Jasper report according to the context from which the report is invoked. For example, when invoking a report from the School folder, displayed inside the School UI, it will pass the current value of schNo. The parameter accepting the school ID **// | ||
- | |||
- | For reports relating to a set of schools, you may use the parameter names corresponding to those accepted by the School filter. You can find what those are in '' | ||
- | |||
- | * SchoolNo | ||
- | * SchoolType | ||
- | * District | ||
- | * Island | ||
- | * ElectorateN | ||
- | * ElectorateL | ||
- | * Authority | ||
- | |||
- | In the Schools report page, these parameters will be supplied where possible from the School filter. In this case, the parameters dialog will always be displayed when invoking the report. | ||
- | |||
- | In the general reports page, listing all reports, the parameters dialog will always be displayed; no defaults will be provided by the EMIS. | ||
- | |||
- | === InputControls and Queries === | ||
- | |||
- | We are establishing InputControls and queries to provide dropdown lists for parameters associated to the main kemis code types. If connected to your report, you’ll get a dropdown list for the parameter in both the JasperServer UI and the EMIS UI (when you get a parameter dialog.) | ||
- | |||
- | TODO More details on this soon. | ||
- | |||
- | === Integration with Pacific EMIS === | ||
- | |||
- | To effectively integrate the JasperReport server with the Pacific EMIS you need to make sure the relevant part of the Web.Config is edited accordingly (i.e. jasperUrl, jasperUser, jasperPass). This would likely be different whether you are working in development or deploying to production. | ||
- | |||
- | <code xml> | ||
- | < | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | <add key=" | ||
- | </ | ||
- | </ | ||
- | |||
- | ==== Dashboard Framework ==== | ||
- | |||
- | === General === | ||
- | |||
- | The dashboard framework is built on the collaboration betwen objects of two types: | ||
- | |||
- | * a Dashboard; and its | ||
- | * DashboardChild objects. | ||
- | |||
- | Each DashboardChild provides some rendering (chart, table, map ... ) or some data. The Dashboard provides a set of services to these objects. | ||
- | |||
- | The Dashboard: | ||
- | |||
- | - provides data to the DashboardChild | ||
- | - manages " | ||
- | - is a " | ||
- | - manages the disposition on the page of the Child objects. | ||
- | |||
- | There a couple of models of dashboard, based on the type of data that is made available to the children. | ||
- | |||
- | * CrossfilterDashboard: | ||
- | * PAFDashboard: | ||
- | * ModelDashboard: | ||
- | |||
- | The dashboard functionality is implemented through a combination of: | ||
- | |||
- | * code: typescript class that can be extended to form new angularjs components; | ||
- | * master layouts: implemented via MVC (i.e. razor) master pages used by each dashboard and each dashboard child; | ||
- | * css: to manage dynamic layouts and animation. | ||
- | |||
- | === Layout === | ||
- | |||
- | The dashboard uses masonry.js to layout its children in a grid. The grid is based on units of 150px x 150px. Each child decides what size it wants in these units (e.g. 3x2; 5x4) | ||
- | |||
- | This is then specified in css like this : | ||
- | |||
- | <code css> | ||
- | class=" | ||
- | </ | ||
- | |||
- | === Selected Child === | ||
- | |||
- | The dashboard allows the user to ' | ||
- | |||
- | === Options === | ||
- | |||
- | The dashboard manages an options class whose properties specify possible filters on the data. These properties are named selectedYear, | ||
- | |||
- | A child has access to the options object (via this.dashboard.options) and can set its properties directly. For example, this can be in response to clicking a bar in a chart, or clicking a row in a grid. For example: | ||
- | |||
- | * the user clicks a bar in a chart | ||
- | * the click handler in the child component sets the option appropriately | ||
- | |||
- | < | ||
- | this.dashboard.options.selectedDistrict = < | ||
- | </ | ||
- | |||
- | * the dashboard detects the option change, and may action it if required | ||
- | * the dashboard communicates the option change to all children. | ||
- | * this fires the onOptionChange event in each child, which executes any reconfiguration | ||
- | |||
- | In a CrossfilterDashboard, | ||
- | |||
- | === Communication === | ||
- | |||
- | Each child holds a strongly-typed reference to its dashboard. This is implemented via the require option in the component definition class. (see earlier comment). Communication from the dashboard to the children is all handled by bindings, so there is no need for the child to set up any watchers. | ||
- | |||
- | The base classes respond to these bindings by firing particular events; so when developing a child component, you need only to derive from the base class, then override the event to respond to the binding change. | ||
- | |||
- | Bindings and their events are: | ||
- | |||
- | < | ||
- | dashboardReady (onDashboardReady) | ||
- | </ | ||
- | |||
- | Signals that the dashboard has prepared data ready for consumption by the children. The child component should implement any setup in '' | ||
- | |||
- | The property '' | ||
- | |||
- | < | ||
- | optionChange (onOptionChange) | ||
- | </ | ||
- | |||
- | Receive an ' | ||
- | |||
- | This value is passed to the '' | ||
- | |||
- | < | ||
- | selectedChild | ||
- | </ | ||
- | |||
- | The selected Child has changed. The child can check if it has become the selected child and can react accordingly. Note that while children get explicit notification of such changes, many responses can be implemented without any action in code. Mechanisms to facilitate this include: | ||
- | |||
- | * Crossfilter: | ||
- | * ng-class / css | ||
- | * a table can make use of utility functions in the base ChildDashboard class, and in the options class, css and the ng-class and ng-show directives to render changes in selected options (e.g. ''< | ||
- | |||
- | === Reporting === | ||
- | |||
- | The dashboard child may have an associated report in the Jasper report tree. This can be hard-coded in the defaultReportPath property of the child, or else passed in via the binding reportPath (i.e. report-path). Default handling is: | ||
- | |||
- | * when a report is set, an icon appears in the child' | ||
- | * Clicking this item runs the report | ||
- | * the child can implement setReportContext to set up report parameters; this is intended to be used to do any mappings between the current dashboard options and the report parameters. | ||
- | * As usual , any required parameters that are not supplied will be prompted for at runtime. | ||
- | |||
- | ===== Low Level Documentation and API ===== | ||
- | |||
- | The lower level documentation about software design, application programming interfaces, small gotchas and all other nitty-gritty details about the source code is written directly inside the source code. It would be nice to eventually be able to extract and export to hard copy formats such as HTML or PDF using a tool like [[http:// | ||
- | |||
- | Since many things are yet undocumented here are a few things to keep in mind. | ||
- | |||
- | * there' | ||
- | * JSON is the data format used by the Web Api (except for the AtAGlance call, see next point). | ||
- | * The AtAGlance pages are built from a static Xml file containing a table of aggregated values. Particular values are dug out of this Xml using Jquery as a kind of client-side " | ||
- | |||
- | ===== eSurvey Technology ===== | ||
- | |||
- | <note warning> | ||
- | |||
- | The Pacific EMIS makes use of what we call "PDF eSurveys" | ||
- | |||
- | ==== Creating/ | ||
- | |||
- | The first thing to do for anybody creating/ | ||
- | |||
- | These word documents currently could be given from one of the Pacific EMIS team members but ideally eventually it should be included in the software repository and version control there as well. Due to the very large number of data cells to process it is not recomended to try and creating the whole survey into a single big word document, but one should break it down into several documents and then re-attached together into a single PDF once complete. | ||
- | |||
- | The process for creating new eSurveys for a given country is something like this: | ||
- | |||
- | - Go through a given eSurvey (i.e. Primary School Annual Survey) from Kiribati and decide what part of the eSurvey applies to you. | ||
- | - Collect all the Kiribati broken down word documents for a given eSurvey (i.e. Primary School Annual Survey) and download them somewhere on your workstation | ||
- | - Pick the relevant part that you need for your eSurvey. | ||
- | - Edit what needs to be edited (e.g. some countries call education | ||
- | - Save your word document as another name (e.g. SIEMIS_PRI_TRIN.docx | ||
- | - Generate the PDF for this word document using the CenoPDF export to PDF feature (not the MS Word export to PDF). | ||
- | - Do this for all the word documents to get all the data grid needed | ||
- | - Combine all the generated PDF documents into the final PDF eSurvey | ||
- | |||
- | < | ||
- | > " | ||
- | |||
- | > " | ||
- | </ | ||
- | |||
- | <note important> | ||
- | There is a small issue making the final generated eSurvey missing, or more specifically hiding some labels. There is an easy work around. Open every CenoPDF generated document into Adobe Acrobat and save the document without making any changes. Accept to override the file. Run the final step 8. above after doing this only. | ||
- | </ | ||
- | |||
- | The process for editing would be much simpler. | ||
- | |||
- | - Locate the word document that needs to be edited or if you need to create a new document create one. | ||
- | - Generated the PDF for the one you changed. | ||
- | - Attach all the PDF document together into the new PDF eSurvey and increase its revision number | ||
- | |||
- | ==== PDF eSurvey Manager ==== | ||
- | |||
- | Currently the PDF eSurvey Manager is a standalone desktop application that must be installed on a machine to " | ||
- | |||
- | * Read existing school surveys from a database (production or a test database) | ||
- | * Pre-populate surveys with some data before sending them to schools | ||
- | * Upload completed surveys into the database (again, production or a test database) | ||
- | |||
- | The PDF eSurvey Manager repository is available at FIXME INCLUDE LINK TO REPO. But you only need to download the executable unless you are a developer wanting to fix or improve the tool. Detailed step by step instructions on how to install, configure and use the PDF eSurvey Manager belong in the User Guide since they are the target audience. | ||
- | |||
- | ==== PDF eSurvey Process ==== | ||
- | |||
- | The PDF eSurvey compliments the new online web user interface. For schools with a more reliable Internet connection they can directly access the survey form online and submit directly in the web Pacific EMIS application. Other schools without access to a reliable Internet connection but with access to a laptop or large tablet running the freely available [[https:// | ||
- | |||
- | A more detailed user-oriented process is documented in the User Guide, but in essence it goes like this: | ||
- | |||
- | - Start the eSurvey Manager | ||
- | - Create a pre-populated survey for one or more schools. Pre-populated eSurveys contains some important information | ||
- | - Distribute those pre-populated eSurveys to their respective schools on a USB stick or email if that have it. | ||
- | - School fill up their surveys as before but directly on a computer instead of paper. | ||
- | - Schools return the filled eSurveys on the same USB stick or email | ||
- | - Data Entry Officers look through the eSurveys for any issues and make sure it is all correctly completed | ||
- | - Start the eSurvey Manager and load the data from the PDF eSurvey into the database | ||
- | - Verify all data was uploaded successfully by browsing to the survey on the Pacific EMIS online web application | ||
- | |||
- | ===== Data Collection Workbook ===== | ||
- | |||
- | This is the newest most comprehensive main data collection tool. It collects school' | ||
- | |||
- | ==== Workbook Connections and Names ==== | ||
- | |||
- | |||
- | Set the data connection to the country' | ||
- | |||
- | {{ : | ||
- | |||
- | Naturally, the lookups in List sheet will need to be changed. Use the Name Manager from the Formula top menu in excel to make sure you adapt their new range since the number of lookups will often change. | ||
- | |||
- | {{ : | ||
- | |||
- | ==== Workbook Data ==== | ||
- | |||
- | Some of the data from the workbook may not always have a place in the SQL schema. In those cases the DB stored the XML parts. It could be queried like this. | ||
- | |||
- | |||
- | <code sql> | ||
- | SELECT TSV.schNo | ||
- | , TSV.svyYear | ||
- | , SS.ssSchType | ||
- | , tchFirstName | ||
- | , tchFamilyName | ||
- | , tcheData.value(' | ||
- | , tcheData | ||
- | , tchClass | ||
- | , tchClassMax | ||
- | , tchSector | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | , tcheData.value(' | ||
- | FROM pTeacherRead.TeacherSurveyV TSV | ||
- | INNER JOIN SchoolSurvey SS | ||
- | ON TSV.ssID = SS.ssID | ||
- | ORDER BY tchClass | ||
- | </ | ||
- | |||
- | We can effectively have values pass through from the workbook straight to the SQL server, and have them appear in views, without finding a home for those values in the relational storage. | ||
- | |||
- | ==== Workbook Commits to Repository ==== | ||
- | |||
- | The workbooks are also committed into the repository of the Census Workbooks under external tools. Note a macro needs to be run before committing changes to the workbook. Run the macro from within the folder where the workbook has changed. For example, in '' | ||
- | |||
- | * All the sheets in the workbook | ||
- | * All the list objects, and the field names in each list | ||
- | * All the “defined names” in the workbook, and their formulas. | ||
- | |||
- | This is done prior to committing and will make it possible to diff key structural changes to the workbooks, without having to visually examine them. | ||
- | |||
- | |||
- | ===== Security Considerations ===== | ||
- | |||
- | Security is an increasingly important aspect of any project and the Pacific EMIS is no exception. This section describes the security framework of the project. | ||
- | |||
- | ==== Authentication ==== | ||
- | |||
- | Currently in progress: User Roles Implementation | ||
- | |||
- | ASP.NET Identity includes a concept of " | ||
- | |||
- | Web Api lets you decorate methods with a Role attribute to determine which role(s) can access that method so you can implement server side security this way. On the client, we send the Role memberships to the client with the Bearer Token, so they are accessible in the client-side code. This is the package that comes down in response to '' | ||
- | |||
- | {{ : | ||
- | |||
- | In particular, the module *angular-permission* gives a simple way to tie an authorization condition to a state in ui-router so you cannot navigate to that state if the condition is not met. So the intention is to set up conditions matched to Role membership, and assign these on the states on the client, just as we do to the corresponding functions on the server. | ||
- | |||
- | So I think we can use these structures to give us quite fine-grained control over authorization for various functions. What we need are: | ||
- | |||
- | * abstract definitions of rights represented as Roles (e.g. can save a school, can read teacher info) and | ||
- | * a mechanism to map into such Roles from domain groups | ||
- | | ||
- | Other Notes. | ||
- | |||
- | * The ASP.NET Identity code was modified to support logins using an | ||
- | |||
- | ==== Authorization ==== | ||
- | |||
- | The Pacific EMIS uses a granular permissions architecture that divides the application into topics, and assigns rights to the user in that topic, example: | ||
- | |||
- | * school; | ||
- | * teacher; | ||
- | * establishment; | ||
- | * enrolment; | ||
- | * survey; | ||
- | * finance; | ||
- | * infrastructure; | ||
- | | ||
- | Rights are: | ||
- | |||
- | * Read : may read topic data | ||
- | * ReadX: may read extended topic data | ||
- | * Write: may write basic topic data | ||
- | * WriteX: may write extended topic data | ||
- | * Admin: may administer data in this topic; for example manage lookup lists | ||
- | * Ops: may perform any specific data manipulation operations in this topic. | ||
- | |||
- | Some rights imply others (e.g. ReadX => Read, WriteX => ReadX, WriteX => Write) | ||
- | |||
- | In the Pineapples database each Topic/Role is represented as a **Role** (e.g. pEstablishmentRead). These roles are called **Functional Roles**. The user (logged in to the database using Windows Authentication) belongs to a role representing their user group (e.g. FinanceOffice) and these roles are called **Organisational Roles**. Each **Organisational Roles** is a member of a set of **Functional Roles**. These membership bestow database permissions on the logged in user. | ||
- | |||
- | However, the database connection from the web site is made in the name of the service account running the web site, so this model cannot work. Using impersonation limits scalability because database connections cannot be reused. So we need to enforce the user privileges in other ways. | ||
- | |||
- | At the **server** the user must be prevented from connecting to any API endpoint to which they do not have permission (e.g. cannot edit a school record if not assigned to pSchoolWrite.) On the **client**, the user interface should reflect operations that the user is not permitted to perform (e.g. the edit button in the School Item form is only available if the user is in pSchoolWrite) . | ||
- | |||
- | Note that client side permission are treated as a " | ||
- | |||
- | === More on Permissions === | ||
- | |||
- | FIXME - cleanup with all content above. | ||
- | |||
- | Pacific EMIS Online determines the permissions you have from your AD group memberships. It finds all your AD group memberships in AspNetUsers, | ||
- | |||
- | < | ||
- | |||
- | |||
- | {{ : | ||
- | |||
- | The permission you see here encapsulates the permissions you get shown shown in the Profile (click on your user name). Each character in the Permission hash represents one topic in the list below. The value of that character is the particular permission(s) you have. | ||
- | |||
- | {{ : | ||
- | |||
- | If you compare these 2 screen prints, you’ll observe that: | ||
- | |||
- | * o = all permissions | ||
- | * 0 (zero) = no permission | ||
- | * 3 = read + readx | ||
- | * ? = read + readx + write + writex | ||
- | * etc. | ||
- | |||
- | In fact, this is not as strange as it may appear: treat the permissions as a byte-map: Read = 1 ReadX = 2...Admin = 32. Then add them up (e.g. read + readx + write + writeX = 15.) Add 48 to this (= 63). Convert to an asci character = "?" | ||
- | |||
- | < | ||
- | |||
- | |||
- | However, these permissions are AGGREGATED, that is Pacific EMIS combines the permissions form each AD group you belong to. | ||
- | |||
- | < | ||
- | |||
- | === Implementing Authorization as Claims === | ||
- | |||
- | These granular permissions will be determined at login time, and encoded as claims in the bearer token. When an API endpoint is called, authorization is determined by interrogating the claims in the current **ClaimsIdentity**. Further, the permissions information is sent to the client at login time, along with the token. This enables the client-side code to access this information when configuring the UI. | ||
- | |||
- | To keep the data small, the permissions will be hashed into a short string. Each character of the string will represent a topic. Since their are 6 possible rights for each topic, there are 64 possible values for the topic 0--63. Note that the dependencies between rights mean that in actuality, many of these combinations cannot be used. Adding 48 to this value produces a displayable character in the range 48--111. This is the character included in the string to represent that topic. In this way, the permission grid is rendered as an 11 character string. | ||
- | |||
- | === Server-side Implementation === | ||
- | |||
- | An attribute '' | ||
- | |||
- | === Client-side Implementation === | ||
- | |||
- | Is based on '' | ||
- | |||
- | <code html> | ||
- | <span permission permission-only=" | ||
- | </ | ||
- | |||
- | === Assigning Permissions === | ||
- | |||
- | For **AspIdentity authentications**, | ||
- | |||
- | For **AD authentications**, | ||
- | |||
- | === Menu Control with Authorization === | ||
- | |||
- | When you log in using an AD account | ||
- | |||
- | There are three types of entry in the Navigation table: menu IDs, headings, and actions. The menu IDs are items that define entire menus. These value are assigned to users and groups in the MenuKey field in AspNetUsers table. | ||
- | |||
- | < | ||
- | |||
- | see ALL and PCRU records from figure below. | ||
- | |||
- | {{ : | ||
- | |||
- | For these items: you define | ||
- | |||
- | * Children – this is a set of other entries in this table, separated by | | ||
- | * Homestate – the page to go to when you first log in. (this is a “state” in the Angularjs client-side code) | ||
- | * MenuPriority – priority for the menu, to choose between multiple menus that a user may have. | ||
- | |||
- | Headers represent headings and subheadings in the menu tree. They define: | ||
- | |||
- | * Icon – fontawesome classes for the icon to display beside this menu item | ||
- | * Label – label to display in the menu | ||
- | * Children – list of submenus or actions under this heading | ||
- | |||
- | Finally there are actions; these define a function to invoke the application: | ||
- | |||
- | * Icon – fontawesome classes for the icon to display beside this menu item | ||
- | * Label – label to display in the menu | ||
- | * State – the angularjs state to go to when this item is selected. | ||
- | |||
- | This is the menu PCRU in action: | ||
- | |||
- | {{ : | ||
- | |||
- | If you follow the chain down from the PCRU menu, through its children and their children, you’ll see how this menu is put together. | ||
- | |||
- | <note tip>This can go as many levels as you want!</ | ||
- | |||
- | Technically, | ||
- | |||
- | {{ : | ||
- | | ||
- | ==== SSL/TLS Encryption ==== | ||
- | |||
- | The application support encrypted communication (i.e. HTTPS). In development the embedded web servers already serves pages through HTTPS. In production it would have to be configured to be served on HTTPS with redirect from HTTP to HTTPS to encsure this. Details to achieve this will be documented in the Systems Administrator Guide. | ||
- | |||
- | ==== Latest Top 10 Security Risks ==== | ||
- | |||
- | The project should always be measured against OWASP' | ||
- | |||
- | ==== Integrated Penetration Testing ==== | ||
- | |||
- | The above guidelines and procedures should offer an excellent starting point to ensure a secure web application. Of course, securing a web application should not stop here. We would like to see a more integrated penetration testing process. There are a number of tools that can be used to help support this process. Most of those tools have a relatelively steep learning curve but they are worth the time investment. | ||
- | |||
- | After some time evaluating several free software tools that were either recommended by OWASP or considered promising projects we have come up with a short list of tools to watch: | ||
- | |||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[http:// | ||
- | |||
- | One or more of those tools could eventually be integrated into the development process. At first only making use of simple features such as automated scans and slowly integrating more complicated robust testing processes one by one. As these new processes come to live they should be clearly documented here with instructions on how to use the tools. | ||
- | |||
- | ===== Project Documentation ===== | ||
- | |||
- | Higher level documentation (i.e. User Manual, Systems Administrator Manual and this Developer Manual) is prepared using the collaborative tool [[http:// | ||
- | |||
- | ===== Functions and Data ===== | ||
- | |||
- | A whole lots of things useful to know when developing on this Pacific EMIS. What will be documented here will be similar to low level documentation but not quite that. Like miscellaneous low level stuff [argh! cringing on my own words]. | ||
- | |||
- | ==== Data Warehouse ==== | ||
- | |||
- | The database has numerous tables, view, procedures, etc. It would be daunting to get good data out of a highly normalised schema. For this we have the data warehouse layer. The data is exposed to developers, data managers and end-users in a more accessible format through this data warehouse layer. All tables and views with the schema warehouse (i.e. starting with warehouse.*) form this data warehouse layer. | ||
- | |||
- | {{ : | ||
- | |||
- | They should always be used when possible instead of building large queries from scratch to access data. This will ensure a consistent view of the data across various presentation layers (e.g. power point presentations, | ||
- | |||
- | ==== Survey Year Filter ==== | ||
- | |||
- | Implemented through a new angular filter, surveyYear. This relies on a sysParam, SURVEY_YEAR_FORMAT which is a template for the format. The template may contain these tokens: | ||
- | |||
- | * yyyy : 4 digit survey year | ||
- | * yy : 2 digit survey year | ||
- | * nnnn : 4 digit next year | ||
- | * nn : 2 digit next year | ||
- | |||
- | e.g. token SYyyyy-nn for value 2015 produces SY2015-16 | ||
- | |||
- | This is incorporated into default school SurveyList.cshtml to get started but everywhere a school year is used this filter should be used to display the full school year. | ||
- | |||
- | For reporting it may be useful to get this conversion done in the server, in the recordset presented to the report. For this you can use the Sql UDF common.surveyYearFormat like this. | ||
- | |||
- | <code sql> | ||
- | Select common.surveyYearFormat(svyYear) surveyYear | ||
- | from SchoolSurvey | ||
- | </ | ||
developer_manual.1540177291.txt.gz · Last modified: 2021/02/02 02:10 (external edit)