164 Commits

Author SHA1 Message Date
Gary Sharp 83e9b7a832 Beta Release: v2.0.0626 2014-06-26 14:54:48 +10:00
Gary Sharp a3a92245ae Update: SignalR 2.1
https://github.com/SignalR/SignalR/releases/tag/2.1.0
2014-06-19 16:02:42 +10:00
Gary Sharp 045fb0b65d Complete #48: Migrate Role Claims
To ease upgrading to vNext, migrate claims so behaviour is roughly the
same.
2014-06-19 14:51:16 +10:00
Gary Sharp 304ffd7ee1 Remove depreciated projects/libraries 2014-06-19 13:59:31 +10:00
Gary Sharp 8b74dbabf5 Bug Fix #49: Update group when attachment removed 2014-06-19 13:56:11 +10:00
Gary Sharp 7f8ed7e752 Feature #52: UserExt Auth methods for expressions
Extension methods can be used to test for user authorization (against
claims) within Expressions
2014-06-17 14:31:11 +10:00
Gary Sharp 84a4ba281f UI Improvements: info-box css 2014-06-17 00:00:56 +10:00
Gary Sharp 34842012b7 Bug Fix: Webcam Attachment in <= Win 7
Flash video overlay was hiding the Comments model dialog. The flash
object is now hidden where <= Win 7 is detected (navigator.userAgent).
2014-06-16 23:10:45 +10:00
Gary Sharp a819d2722a Feature #49: Active Directory Managed Groups
Document Template Attachments, Device Batches, Device Profiles and User
Flags can be associated with an Active Directory group. This AD group is
then automatically synchronized with relevant User/Machine accounts.
Contains various other UI tweaks and configuration enhancements.
2014-06-16 22:21:31 +10:00
Gary Sharp ebf78dd08d Bug Fix: Sharepoint Public Reports XSLT
Incorrect serialization of HeldDeviceItem and referencing in the XSLT.
2014-06-11 21:56:50 +10:00
Gary Sharp 6186237028 Bug Fix: Bulk Generate Documents UserId Domain
Where no domain is provided, the primary domain should be assumed.
2014-06-11 21:32:50 +10:00
Gary Sharp 513397779d Bug Fix: Org Logo config minor UI tweak
The update dialog height was hard-coded and partially obstructed the
input element.
2014-06-11 21:29:12 +10:00
Gary Sharp 815216fd73 Update #26: User Flags Bulk Assignment
Add or Override User Flag assignments in bulk.
2014-06-11 21:23:32 +10:00
Gary Sharp 8254e7ec5a Feature #51: Markdown Support
Markdown implemented in Job Logs, Job Queue comments, various other
places.
2014-06-11 14:51:51 +10:00
Gary Sharp 4c3a68da30 Feature #26: User Flags
Flags can be associated with Users. Includes minor updates to Job Queues
and improved visibility of user information.
2014-06-10 17:16:24 +10:00
Gary Sharp b64ac3b16f Feature #44: Image capture WebRTC & HTML5 FileIO
Silverlight was previously used to capture webcam pictures and upload
file attachments. HTML5 FileIO is now used for all attachment uploading
- including drag-drop support. WebRTC is used to capture webcam images -
this falls back to a Flash polyfill when WebRTC isn't supported.
2014-06-05 21:01:43 +10:00
Gary Sharp d040ab094c Bug Fix: Floats must come first [Firefox]
Floated elements need to come first, otherwise float layout occurs
underneath non-floated content.
2014-06-05 20:57:45 +10:00
Gary Sharp a0e18ef963 SignalR Bug Fixes & Minor UI Changes
Document Template import status and Device Enrolment status fixes.
Attachment download fixes for SignalR foreverFrame transport. Database
queries for Devices, Jobs and Users updated. Device attributes (model,
profile, batch) now shown in various places.
2014-06-03 12:36:48 +10:00
Gary Sharp 830a9c8d05 Update: Minor styling changes
Dialogs reposition to center when window resized & Update heading moved
so that background is correctly shown.
2014-06-02 20:25:43 +10:00
Gary Sharp ea51ba1f88 Bug Fix: Scheduled Task Status Updates
Scheduled Task status is more reliable
2014-06-02 20:02:48 +10:00
Gary Sharp 5510d34885 Bug Fix: Document Generation and SignalR iFrame
Performing page navigation (within an iFrame, or the top window) causes
the foreverFrame transport in SignalR to abort which takes several
seconds to reconnect. Popup windows are now used to navigate to Document
Generation API when the foreverFrame transport is in use.
2014-06-02 19:06:07 +10:00
Gary Sharp be25569245 Update 3rd Party Libraries
Json.NET, jQuery, jQuery UI, modernizr, moment.js, Highcharts, TinyMCE,
normalize.css, T4MVC, RazorGenerator, Reactive Extensions
2014-06-02 02:11:03 +10:00
Gary Sharp 7af6a2220c Update #41: Device Detail: Keyboard
'Keyboard' Device Detail added.
2014-06-01 23:42:08 +10:00
Gary Sharp 4cd57f4a90 Update: SignalR 2.0.3 Migration; Noticeboards
Migrate all SignalR 1.x Persistent Connections to SignalR 2.x Hubs.
Abstracts ScheduledTaskStatus with core interface and adds a Mock for
optional status reporting. Noticeboards rewritten (with new theme) to be
more resilient and accurate.
2014-06-01 23:27:07 +10:00
Gary Sharp f6fae26bc7 Update #9: Hide decommissioned batches by default 2014-05-28 15:01:06 +10:00
Gary Sharp 7cad69598f Update: Device Trusted Enrolment Import/Export
Added AllowUnauthenticatedEnrol to import and export functionality.
2014-05-27 17:08:39 +10:00
Gary Sharp 4e69253852 Update: Device Battery field, Excel CSV Format
Device Battery import & export; Leading zero workaround for Excel
2014-05-27 16:36:42 +10:00
Gary Sharp 825627e345 Bug Fix: Update Admins blocked all Admins
The updated subject hash was case-sensitive when it should have been
reinitialized with the OrdinalIgnoreCase string comparer.
2014-05-27 13:49:13 +10:00
Gary Sharp e9042f7666 Feature #33: Enhanced Device Importing
Dynamic device importing. better input parsing and 5 additional import
fields.
2014-05-25 17:33:18 +10:00
Gary Sharp 6a45348bdb Bug Fix: Sort Job Queue menu 2014-05-25 16:30:01 +10:00
Gary Sharp f3351af9e8 Bug Fix: Indicate failed task if waiting
If using ScheduledTaskStatus.WaitUntilFinished, only return true if the
task completed successfully.
2014-05-25 16:21:33 +10:00
Gary Sharp a5e38406d1 Update: Font Awesome 4.1.0
Font Awesome updated and added several new icons as options for job
queues.
2014-05-25 16:15:59 +10:00
Gary Sharp 3c759ac4d7 #34 Update: Update LastNetworkLogon Dates
Perform UpdateNetworkLongDates task during export if the appropriate
field is selected.
2014-05-22 12:29:03 +10:00
Gary Sharp f70261aa25 #34 Update: Additional Validation & UI Changes
Ensure at least one field is selected, and UI improvements.
2014-05-22 12:11:26 +10:00
Gary Sharp 3fdb4f1053 #34 Feature: Detailed Device Exporting
Many additional device properties are available to export. The previous
export configuration is remembered.
2014-05-22 01:22:57 +10:00
Gary Sharp 53ca13c7f4 Update: Name clarification
Name updated in various places: "Disco ICT"
2014-05-12 23:55:59 +10:00
Gary Sharp 185c4682f0 Certificate provider log update
Add 'UpdatedCertificate' event and renamed some existing log types.
2014-05-12 23:50:29 +10:00
Gary Sharp 39c3bf9fc7 Bug Fix: Initial Config Typo
Thanks to Elijah Solly for finding this one
2014-05-10 20:50:14 +10:00
Gary Sharp c87ee6a0e7 Update: jQuery Validate & Unobtrusive Updated 2014-05-10 20:26:57 +10:00
Gary Sharp 4a08c8c275 Certificate Provider Log Additions
Add Disabled and Deleted certificate log events
2014-05-10 20:26:03 +10:00
Gary Sharp fb6067afc3 Update: Configuration Optimisation and Caching
Loads entire configuration at start-up (rather than scope-based
loading). Deserialization occurs once, with the resulting value cached
and replayed if the requested type matches.
2014-05-07 22:45:59 +10:00
Gary Sharp 6b2cd47610 Bug Fix: Targeted user search without domain
If no domain is specified, the primary domain should be assumed
2014-04-23 13:20:03 +10:00
Gary Sharp 392de396df Bug Fix: Pointer/Touch events triggered navigate
When using touch the anchor navigates immediately even though the Click
event has preventDefault()
2014-04-23 12:59:28 +10:00
Gary Sharp 3cf6d5475d Bug Fixes: enrolment, assignment and search order 2014-04-22 13:55:46 +10:00
Gary Sharp 74df073b29 Bug Fix: AD User Searching
Group properties were loaded instead of User properties
2014-04-22 10:12:03 +10:00
Gary Sharp 09c2a24222 Update #42: AD Migration
Refactor to target specific Domain Controllers, with failover.
2014-04-21 21:43:13 +10:00
Gary Sharp 43fc622121 Use AD site-servers where possible 2014-04-17 17:37:59 +10:00
Gary Sharp b8ec44293f Parallelize AD searching
Where multiple queries are required to complete a search, the query is
parallelized
2014-04-17 17:00:02 +10:00
Gary Sharp 36100bfef5 Optimise for quick AD user searching
Avoids loading users groups when not needed
2014-04-17 15:49:22 +10:00
Gary Sharp b77bdf16f5 Bug Fix: Search fails with unassigned devices 2014-04-17 15:47:15 +10:00
Gary Sharp 5aede7153c Bug Fix: Avoid unnecessary AD queries
In multi-domains, parent domains were searched for child containers.
2014-04-17 15:23:47 +10:00
Gary Sharp 4fc6c3ca9f Status when loading AD Organisational Units
Large domains can take significant time (several seconds) to load the
domain structure (where there are 1000's of OUs)
2014-04-17 13:08:37 +10:00
Gary Sharp d86280ae3e Fix various Multi-Domain bugs 2014-04-16 13:16:08 +10:00
Gary Sharp 2281313966 App Maintenance Theme
Updated to 'Initial Config' theme
2014-04-16 12:59:11 +10:00
Gary Sharp 740e806ef0 Fix #46: Job Table overflow ellipsis 2014-04-13 23:33:15 +10:00
Gary Sharp f35f9d3661 Update: Dialog styling & animation
Dialogs slide & fade in. All appear in the same spot (50px from top)
2014-04-13 23:18:24 +10:00
Gary Sharp 201acc1976 Feature #43: Specify Admins at Initial Config
Disco Administrators can be specified during the Initial Configuration
2014-04-13 23:17:01 +10:00
Gary Sharp a4f4b7d0b3 Initial Config Theme & File Store Changes
Update theme & remove dynatree requirement
2014-04-13 20:19:02 +10:00
Gary Sharp 41dc002ef8 Update #43: Disco Administrators are configurable 2014-04-11 19:57:51 +10:00
Gary Sharp e984221c95 Bug Fix: User Attachment Refs, AD Group Domain
User Attachments updated in the DataStore to reflect new UserId (which
includes the domain); AD Groups were using DnsName instead of
NetBiosName.
2014-04-11 19:56:17 +10:00
Gary Sharp 3238a916a2 Removal of Old AD Interop Files 2014-04-10 22:22:13 +10:00
Gary Sharp db73cc1a12 Feature #42: Active Directory Interop Upgrade
AD Interop moved to Disco.Services; Supports multi-domain environments,
sites, and searching restricted with OUs.
2014-04-10 17:58:04 +10:00
Gary Sharp b841c6b2c0 Bug Fix: Warranty Repair list 2014-03-18 14:18:59 +11:00
Gary Sharp 69091e0785 Update: Create Job redirect shows Job Id 2014-03-18 14:10:50 +11:00
Gary Sharp 3d5f71aba9 Add LICENSE.txt to repository
The license has always been present
(Disco.Web/Areas/Public/Views/Public/Licence.cshtml), but adding to the
repository is considered best-practice.
2014-03-18 13:26:04 +11:00
Gary Sharp da166e5cd2 Update: LESS Compiler Updated
Minor compiled css formatting changes
2014-03-03 14:31:07 +11:00
Gary Sharp 74775e9e3d Bug Fix: Unauthorized HTTP Status Desc length
Status Description was to long causing a 0-byte result to be returned
(HTTP 504).
2014-03-03 14:29:17 +11:00
Gary Sharp 96c5860080 Bug Fix: Statistics for Quick-Logged Jobs
Jobs now perform a check when Quick-Logged and update Statistics
accordingly.
2014-02-20 10:56:06 +11:00
Gary Sharp 6ac87633ac Update: Quick Log & Queue Support 2014-02-18 17:26:03 +11:00
Gary Sharp 0db43d9200 Bug Fix: Delete Jobs with Queue references
Job Queue references were not deleted when the job was deleted causing a
database reference constraint error.
2014-02-18 17:03:35 +11:00
Gary Sharp a82e039140 Bug Fix #4: Only reference jobs where device held 2014-02-18 17:00:14 +11:00
Gary Sharp bfa3bf1e94 Update #4: Import Location Lists 2014-02-18 16:45:58 +11:00
Gary Sharp 5be747afbc Feature #4: Pre-defined/Restricted Locations
Configurable list and location suggestions. Ability to restrict
locations. Shows 'occupied' locations.
2014-02-17 21:44:34 +11:00
Gary Sharp ed7caf8b4a Bug Fix: Job Index Authorization Check
The LongRunningJobs claim is checked instead of the StaleJobs claim
which resulted in an NullReferenceException for users without StaleJobs
authorization.
2014-02-14 21:16:17 +11:00
Gary Sharp 7027b33fe2 Bug Fix: Job Quick-Logging with Queues
Jobs logged cannot be quick-logged if they are added into a queue.
'Device Held' can only be configured if the authorization is given.
2014-02-13 22:26:26 +11:00
Gary Sharp 68256d7abd Feature #37: Stale Jobs
Stale Jobs replaces Long-Running Jobs on the homepage. Last Activity is
added to the job table.
2014-02-13 22:17:49 +11:00
Gary Sharp 2ac3a9bdd3 Bug Fix: Minor permission enforcements
Also some UI tweaks.
2014-02-13 15:27:04 +11:00
Gary Sharp a6a65c54c7 Bug Fix: Incorrect default date in dialog 2014-02-13 15:26:10 +11:00
Gary Sharp 7bdbeb6a82 Feature #35: Livestamp implemented
Humanized dates now update automatically when a page is left open for
some time.
2014-02-11 16:50:03 +11:00
Gary Sharp c4cc54d316 Bug Fix: Job Expected Date UI
Incorrect format displayed - which couldn't be interpreted by the
date-picker.
2014-02-11 13:59:16 +11:00
Gary Sharp 3ae657f2ba Update Minor Job UI tweaks
Job Queue 'Tasks' wording; Job ui-tabs item counting
2014-02-10 17:16:31 +11:00
Gary Sharp 2e7b66ee5b Update: Change UI for "Show Closed Jobs"
Move to a button at the bottom of the list.
2014-02-06 18:57:10 +11:00
Gary Sharp 6d54f3f972 Update: Quick Search supports shortcuts
!/#/@ Shortcut Support
2014-02-06 18:18:46 +11:00
Gary Sharp cd31ba4a6c Feature: Quick Search
Device/Job/User Search refactoring. Quick-Search implemented.
2014-02-06 16:11:45 +11:00
Gary Sharp 9ea0273936 Update: Minor styling for Job Lists
Especially for 'No Jobs' or 'All Jobs Closed' situations.
2014-02-06 12:22:15 +11:00
Gary Sharp 7748f15d76 Update: Auth Claims Refinement, Job Creation
Auth Claims for Job Creation types, user details.
2014-02-04 17:41:00 +11:00
Gary Sharp eea71e6eb0 Bug Fix: Could not delete Job Queues 2014-02-04 15:03:19 +11:00
Gary Sharp 3bc8b63700 Bug Fix: Accounting Payment List
"Jobs Awaiting Finance - Awaiting Payment" list was incorrectly
including jobs.
2014-02-04 12:13:11 +11:00
Gary Sharp 6bacf6e3a5 Fix: Navigation and page width styles
Search bar was disappearing
2014-02-04 12:08:59 +11:00
Gary Sharp cc4682875b Change: Rename Undetected Pages permission
Change to: "Process Undetected Pages"
2014-02-04 10:52:49 +11:00
Gary Sharp bfcbcf9da2 Fix: Client Icons
Update to current theme.
2014-02-04 10:52:07 +11:00
Gary Sharp ad28729a85 Change: Job Queue Description not required 2014-02-04 10:51:33 +11:00
Gary Sharp 3f63281dc4 Feature: Job Queues
Also UI style, theme and element changes
2014-02-03 14:50:08 +11:00
Gary Sharp bdb3e1e6b4 Bug Fix #36: Repair computer name template error
Corrects existing invalid computer name templates.
2014-01-23 13:43:23 +11:00
Gary Sharp 10394c4e39 Bug Fix #36: Default Profile name template error
The "Initial Default Workstation Profile" had an incorrect Computer Name
Template set by default. This does not affect newly created Device
Profiles which use a valid template.
2014-01-23 13:36:19 +11:00
Gary Sharp 2ddf4b7bd9 Update: menu separators & text placeholder 2013-12-26 11:53:02 +11:00
Gary Sharp 35391ad1a1 Feature: Thread-blocking task status completion
Thread can be blocked until a task completes (or a timeout period
elapses). Used to wait up to 3 seconds before redirecting to the
TaskStatus when downloading the Plugin Catalogue.
2013-12-25 18:35:19 +11:00
Gary Sharp ab553a05cb Update: FontAwesome Pass 2
Removal of bitmap icons, replacing with vector based icons from
FontAwesome. Includes other UI style changes.
2013-12-25 17:49:30 +11:00
Gary Sharp 20263905f9 Feature: FontAwesome Added
FontAwesome 4.0.3.1 Added, and an initial pass to replace bitmap icons.
2013-12-24 16:22:26 +11:00
Gary Sharp f1ee2937cd Feature: New Theme
New icon, theme, and fuzzy time. Add moment.js
2013-12-24 14:15:07 +11:00
Gary Sharp ec118a3395 Bug Fix #32: ConvertHWarToHNWar Components
Components are now correctly filtered and associated with jobs when
converting from "Hardware - Warranty" to "Hardware - Non Warranty".
2013-12-09 18:47:24 +11:00
Gary Sharp 551b1d3a41 Bug Fix #28: DataStore Drive not present 2013-12-03 11:19:51 +11:00
Gary Sharp 214ecf6212 Bug Fix #31: Restrict AD User Search to Users
Added "objectClass=user" LDAP filter which excludes AD Contacts.
2013-12-03 09:37:21 +11:00
Gary Sharp fad8eae9f4 Bug Fix #30: Upload File & Capture Image Buttons
Now both buttons work as expected, rather than having to refresh that
page to gain access to the other feature.
2013-12-02 17:21:56 +11:00
Gary Sharp 2dd3f5f9ab JobParts\Resources tooltip update
Updated tooltips to reflect discussion in #29
2013-12-02 17:09:00 +11:00
Gary Sharp 8ace60f10d Merge pull request #29 from doctorjbeam/patch-1
Added tooltips to JobParts\Resources.cshtml
2013-12-01 22:06:07 -08:00
Michael Greenhill 136c371b01 Added tooltips to JobParts\Resources.cshtml
Example use of tooltips (title attribute) to give give end users more instruction.
2013-12-02 12:51:38 +11:00
Gary Sharp a5c051916e Version bump for release 1.2.1128 2013-11-28 15:09:56 +11:00
Gary Sharp 4f4dbabf8b Bug Fix: Bootstrapper crash if previously failed
Updated bootstrapper correctly cleans up temporary files left by a
previous run which failed.
2013-11-26 17:30:05 +11:00
Gary Sharp e4c86f1cc1 Bug Fix: Touch support for menu
Support for PointerEvents, MSPointerEvents and Touch with fallback to
Mouse events.
2013-11-20 15:06:37 +11:00
Gary Sharp eabd9671f0 Bug Fix: Touch support for menu
Support for Touch, PointerEvents and Mouse event specifications.
2013-11-19 16:35:03 +11:00
Gary Sharp 9b34abfa29 Bug Fix: Default DeviceProfile DistributionType
The DistributionType is required but was not specified (null) in the
Database Seed (as a result of the move to an enum).
2013-11-19 14:19:41 +11:00
Gary Sharp d1007266c9 Include LumenWorks Framework Dependency
Disco.BI Dependency for CSV Parsing.
2013-11-19 09:55:23 +11:00
Gary Sharp 230b1af9f7 Bug Fix: MVC Layouts to Static 2013-11-14 14:13:23 +11:00
Gary Sharp fe00963cb0 Update: Error UI Updated 2013-11-14 13:34:53 +11:00
Gary Sharp b1048588e7 Bug Fix: Upload attachments required refresh 2013-11-12 12:21:35 +11:00
Gary Sharp 9ac487e7e0 Update: Max Request Length 20MB
Increase from default (4MB)
2013-11-12 12:20:17 +11:00
Gary Sharp 404d5c9120 Update: Silverlight Script Module 2013-11-12 12:12:54 +11:00
Gary Sharp 1cbbf1dde4 Custom Error Handling 2013-11-11 17:04:04 +11:00
Gary Sharp a63041abf2 Bug Fix: Check Box List script
Migrate from .attr() to .prop() as per: http://api.jquery.com/prop/
2013-11-05 16:14:44 +11:00
Gary Sharp bd4f0bd9a7 Bug Fix: jQuery Ext for Firefox 2013-11-05 14:29:53 +11:00
Gary Sharp bc08bd7dc2 Fix #22: PluginWebViewPage ReferenceNullException
Plugin Helper needs to be lazy loaded
2013-10-31 16:44:20 +11:00
Gary Sharp d8fc45ee6f Feature #3: Server SKU support for Enrolment
The Disco Client (which is launched by the Bootstrapper) supports
Windows Server SKUs. Removes dependancy on WLANAPI.DLL. Updates to
enrolment allows for successful addition to System Critial objects (eg.
DC/PDCs) into Disco without making any changes to AD objects.
2013-10-31 14:15:00 +11:00
Gary Sharp fce371231c Fix #25: 'Long Running' status on closed jobs 2013-10-31 12:11:12 +11:00
Gary Sharp 76aead2011 Update #15: Community Reporting
Active Devices are more correctly reported, and metrics on warranty job
vendor logging.
2013-10-29 14:36:29 +11:00
Gary Sharp df633b3591 Feature #7: AC Adapter Device Detail 2013-10-29 13:30:41 +11:00
Gary Sharp 94c7cae443 Feature #19: Allow auto unauthenticated enrolment 2013-10-29 12:26:33 +11:00
Gary Sharp 10a38af08b Feature #20: Assigned User Is Local Admin
Device Profile setting which specifies whether assigned users are set as
Local Administrators. Default is true (which maintains compatibility).
2013-10-28 18:16:22 +11:00
Gary Sharp c13d13c91c Update: 3rd Party Libraries
Newtonsoft.Json 5.0.8; RazorGenerator.Mvc 2.1.2; jQuery 2.0.3; jQuery
Validate Unobtrusive 3.0.0; Microsoft.Net.Http 2.1.10; KnockoutJS 2.3.0;
Highcharts 2.0; T4MVC 3.7.4; TinyMCE 4.0.9
2013-10-28 17:42:38 +11:00
Gary Sharp 7096a511c3 Fix: CheckBoxList checked attribute encoding 2013-10-28 14:11:31 +11:00
Gary Sharp 233d62442c Update #18: UX Document Template Bulk Generating
Improved UX
2013-10-24 22:15:46 +11:00
Gary Sharp 723eeec91e Feature #25: Job General Preferences
Initially to make 'long running job threshold' configurable. Updates to
ManagedJobList and fix for missing GetClaimKeys method (#24).
2013-10-24 18:19:05 +11:00
Gary Sharp 0d60fb422c Update: Plugin Web Helpers
Web Helpers included in UI Extensions and WebHandlers
2013-10-22 13:48:25 +11:00
Gary Sharp cc218a08e4 Update: Install Plugin (or Update)
Check to update the plugin when installing to avoid
uninstall->wait->install cycle.
2013-10-21 20:50:31 +11:00
Gary Sharp 401ae029f1 Update: Use Generics for Compiled View
Also standardize inclusion of StyleSheets/Scripts for Plugin Resources
2013-10-21 20:05:33 +11:00
Gary Sharp 4dfe9ad086 Fix: Computer authorized enrolment
Computer Accounts could not enrol
2013-10-21 20:02:40 +11:00
Gary Sharp 5f9a49bca3 Fix #13: Don't hide initialize errors 2013-10-17 15:31:50 +11:00
Gary Sharp faee1e724e Enhancement: Menu Style #6
Remove transparency; improve text clarity.
2013-10-17 12:44:10 +11:00
Gary Sharp d6859dcde4 Community Services use HTTPS #21 2013-10-17 11:34:22 +11:00
Gary Sharp fdb5d37ec8 Fix: AuthorizationRole.Subjects can be null #24
Fixes the resulting NullReferenceException.
2013-10-17 11:05:22 +11:00
Gary Sharp 51ebc673e7 Fix: Update details device during enrolment #14 2013-10-17 11:03:54 +11:00
Gary Sharp 017b1435d8 Authorization Logging #24
Record 'Access Denied' and any changes to Authorization Roles.
2013-10-15 16:13:41 +11:00
Gary Sharp 7b62eabeee Fix: Job UI Authorization #24
Insurance Claim Form Sent authorization logic was incorrect causing a
NullReferenceException.
2013-10-15 10:12:20 +11:00
Gary Sharp d8c4d13def Fix: Handle User UI when not found in AD #24 2013-10-15 09:17:37 +11:00
Gary Sharp 9784c5d282 Plugin Base WebViewPage #22 & Authorization #24
Plugins have a base WebViewPage to inherit, this offers integration with
various Disco services. Plugins can also add Authorization attributes to
their Web Handlers and Controller Methods.
2013-10-14 20:13:00 +11:00
Gary Sharp 4b822d3ae3 Fix: Assigned User Not Set 2013-10-14 19:58:41 +11:00
Gary Sharp 24751780cc Fix: CurrentUserId returned domain 2013-10-14 16:23:59 +11:00
Gary Sharp 4d19e381fd Authorization Subject Link #24
Create links to user when browsing Authorization Roles. Also removes
uncompiled views from published application.
2013-10-14 12:44:41 +11:00
Gary Sharp ec74039400 User Authorization UI #24
Additional UI to help determining what effective authorization users
have.
2013-10-14 12:12:50 +11:00
Gary Sharp a099d68915 Permissions & Authorization for Users #24
Initial Release; Includes Database and MVC refactoring
2013-10-10 19:13:16 +11:00
Gary Sharp 172ce5524a Update: Managed Modules for All Requests
Run all requests through managed modules. May impact on performance, but
improves compatibility with various IIS configurations.
2013-10-09 13:25:12 +11:00
Gary Sharp 2ad4cd2080 Update: Shorten MacAddress Importing Delay
Reduce from 15 minutes to 5 minutes after startup.
2013-09-12 16:40:14 +10:00
Gary Sharp 2e820cd720 Feature #14: Device Details
Initial Commit - LAN/WAN MAC Addresses
2013-09-12 13:39:39 +10:00
Gary Sharp 75ebfdaa80 Bug: Global search occurs twice 2013-09-12 13:25:30 +10:00
Gary Sharp 122f719e3b Fix #16: Include AD Primary Group when Searching
Fix regression when searching for users.
2013-09-09 17:02:00 +10:00
Gary Sharp 60f7384c97 Update: Job Entity -> Enum Support 2
Support the DistributionType Enum in Device Profiles
2013-09-09 15:09:28 +10:00
Gary Sharp 02b91f1ea4 Fix #17: Computer Name Template Cache
Correctly invalidates the Expression Cache when a Computer Name Template
changes.
2013-09-09 14:39:49 +10:00
Gary Sharp d0aea2401b Feature: Device Lost/Stolen Sub Types
As requested in #1
2013-09-05 18:31:02 +10:00
Gary Sharp 29a6057443 Feature: Decommission Reasons
As requested in #1
2013-09-05 18:23:59 +10:00
Gary Sharp f3efa56750 Update: Job Entity -> Enum Support 2013-09-05 12:45:23 +10:00
Gary Sharp 090322126a Fix #16: Include Primary Group for AD Users
Caches group SIDs and retires unmanaged SID transform PInvoke for
managed equivalents
2013-09-03 20:21:20 +10:00
Gary Sharp d8538d2792 Fix: Remove Unnecessary AJAX at Log Warranty
Page is always refreshed to provide information to Warranty Plugin -
generate address UI at server.
2013-09-02 18:58:49 +10:00
Gary Sharp 37810656fd Fix #12: Update users when logging warranty
Job User is updated when available.
2013-09-02 18:37:30 +10:00
Gary Sharp 3596d325eb Fix #11 : jQuery delegated events for Firefox 2013-08-19 17:36:22 +10:00
1176 changed files with 253527 additions and 106496 deletions
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.SignalR.Utils" version="2.1.0" />
</packages>
+5 -5
View File
@@ -15,10 +15,10 @@ namespace Disco.BI.AttachmentBI
if (Source != null)
{
// GDI+ (jpg, png, gif, bmp)
if (SourceMimeType.Equals("image/jpeg", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("jpg") ||
SourceMimeType.Equals("image/png", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("png") ||
SourceMimeType.Equals("image/gif", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("gif") ||
SourceMimeType.Equals("image/bmp", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("bmp"))
if (SourceMimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("jpg") ||
SourceMimeType.Equals("image/png", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("png") ||
SourceMimeType.Equals("image/gif", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("gif") ||
SourceMimeType.Equals("image/bmp", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("bmp"))
{
try
{
@@ -42,7 +42,7 @@ namespace Disco.BI.AttachmentBI
}
// PDF
if (SourceMimeType.Equals("application/pdf", StringComparison.InvariantCultureIgnoreCase) || SourceMimeType.Contains("pdf"))
if (SourceMimeType.Equals("application/pdf", StringComparison.OrdinalIgnoreCase) || SourceMimeType.Contains("pdf"))
{
PdfReader pdfReader = new PdfReader(Source);
try
+2 -2
View File
@@ -10,9 +10,9 @@ namespace Disco.BI
public static class DataStore
{
public static string CreateLocation(DiscoDataContext dbContext, string SubLocation, DateTime? SubSubLocationTimestamp = null)
public static string CreateLocation(DiscoDataContext Database, string SubLocation, DateTime? SubSubLocationTimestamp = null)
{
return CreateLocation(dbContext.DiscoConfiguration, SubLocation, SubSubLocationTimestamp);
return CreateLocation(Database.DiscoConfiguration, SubLocation, SubSubLocationTimestamp);
}
public static string CreateLocation(SystemConfiguration DiscoConfiguration, string SubLocation, DateTime? SubSubLocationTimestamp = null)
{
+1 -1
View File
@@ -9,7 +9,7 @@ namespace Disco.BI.DeviceBI
{
public static class BatchUtilities
{
public static DeviceBatch DefaultNewDeviceBatch(DiscoDataContext dbContext)
public static DeviceBatch DefaultNewDeviceBatch(DiscoDataContext Database)
{
return new DeviceBatch()
{
+3 -3
View File
@@ -32,7 +32,7 @@ namespace Disco.BI
if (deviceModel == null)
{
// Create the Device Model in a different DataContext so we don't have to commit unrelated changes
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
var addDeviceModel = new DeviceModel
{
@@ -41,8 +41,8 @@ namespace Disco.BI
ModelType = ModelType,
Description = string.Format("{0} {1}", Manufacturer, Model)
};
dbContext.DeviceModels.Add(addDeviceModel);
dbContext.SaveChanges();
database.DeviceModels.Add(addDeviceModel);
database.SaveChanges();
}
// Obtain the Device Model with the in-scope DataContext
+180 -90
View File
@@ -1,16 +1,16 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using Disco.BI.Interop.ActiveDirectory;
using Disco.BI.Extensions;
using Disco.Data.Configuration.Modules;
using Disco.Data.Repository;
using Disco.Models.ClientServices;
using Disco.Models.Interop.ActiveDirectory;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Text.RegularExpressions;
using Tamir.SharpSsh;
using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.CertificateProvider;
namespace Disco.BI.DeviceBI
{
@@ -24,7 +24,7 @@ namespace Disco.BI.DeviceBI
}
private static Regex SshPromptRegEx = new Regex("[\\$,\\#]", RegexOptions.Multiline);
public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext dbContext, string Host)
public static MacSecureEnrolResponse MacSecureEnrol(DiscoDataContext Database, string Host)
{
MacEnrol trustedRequest = new MacEnrol();
string sessionId = System.Guid.NewGuid().ToString("B");
@@ -32,8 +32,8 @@ namespace Disco.BI.DeviceBI
try
{
EnrolmentLog.LogSessionStarting(sessionId, Host, EnrolmentTypes.MacSecure);
EnrolmentLog.LogSessionProgress(sessionId, 0, string.Format("Connecting to '{0}' as '{1}'", Host, dbContext.DiscoConfiguration.Bootstrapper.MacSshUsername));
SshShell shell = new SshShell(Host, dbContext.DiscoConfiguration.Bootstrapper.MacSshUsername, dbContext.DiscoConfiguration.Bootstrapper.MacSshPassword);
EnrolmentLog.LogSessionProgress(sessionId, 0, string.Format("Connecting to '{0}' as '{1}'", Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername));
SshShell shell = new SshShell(Host, Database.DiscoConfiguration.Bootstrapper.MacSshUsername, Database.DiscoConfiguration.Bootstrapper.MacSshPassword);
try
{
shell.ExpectPattern = "#";
@@ -55,7 +55,7 @@ namespace Disco.BI.DeviceBI
output = shell.Expect(":");
EnrolmentLog.LogSessionProgress(sessionId, 27, "Connected, Elevating Credentials");
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, output);
shell.WriteLine(dbContext.DiscoConfiguration.Bootstrapper.MacSshPassword);
shell.WriteLine(Database.DiscoConfiguration.Bootstrapper.MacSshPassword);
System.Threading.Thread.Sleep(250);
output = shell.Expect(SshPromptRegEx);
sessionElevated = true;
@@ -96,7 +96,7 @@ namespace Disco.BI.DeviceBI
shell.Close();
}
EnrolmentLog.LogSessionProgress(sessionId, 100, "Disconnected, Starting Disco Enrolment");
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(MacEnrol(dbContext, trustedRequest, true, sessionId));
MacSecureEnrolResponse response = MacSecureEnrolResponse.FromMacEnrolResponse(MacEnrol(Database, trustedRequest, true, sessionId));
EnrolmentLog.LogSessionFinished(sessionId);
MacSecureEnrol = response;
}
@@ -211,7 +211,7 @@ namespace Disco.BI.DeviceBI
#endregion
public static MacEnrolResponse MacEnrol(DiscoDataContext dbContext, MacEnrol Request, bool Trusted, string OpenSessionId = null)
public static MacEnrolResponse MacEnrol(DiscoDataContext Database, MacEnrol Request, bool Trusted, string OpenSessionId = null)
{
string sessionId;
if (OpenSessionId == null)
@@ -228,7 +228,7 @@ namespace Disco.BI.DeviceBI
try
{
EnrolmentLog.LogSessionProgress(sessionId, 10, "Querying Database");
Device RepoDevice = dbContext.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceProfile").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
if (!Trusted)
{
if (RepoDevice == null)
@@ -240,9 +240,9 @@ namespace Disco.BI.DeviceBI
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "New Device, Building Disco Instance");
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
DeviceProfile deviceProfile = dbContext.DeviceProfiles.Find(dbContext.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = dbContext.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
@@ -252,14 +252,14 @@ namespace Disco.BI.DeviceBI
RepoDevice = new Device
{
SerialNumber = Request.DeviceSerialNumber,
ComputerName = Request.DeviceComputerName,
DeviceDomainId = Request.DeviceComputerName,
DeviceProfile = deviceProfile,
DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false,
CreatedDate = DateTime.Now,
EnrolledDate = DateTime.Now
};
dbContext.Devices.Add(RepoDevice);
Database.Devices.Add(RepoDevice);
}
else
{
@@ -267,7 +267,7 @@ namespace Disco.BI.DeviceBI
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
if (!RepoDevice.DeviceModelId.HasValue || RepoDevice.DeviceModelId.Value == 1)
{
var deviceModelResult = dbContext.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
@@ -280,7 +280,7 @@ namespace Disco.BI.DeviceBI
{
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, RepoDevice.DeviceModelId);
}
RepoDevice.ComputerName = Request.DeviceComputerName;
RepoDevice.DeviceDomainId = Request.DeviceComputerName;
if (!RepoDevice.EnrolledDate.HasValue)
{
RepoDevice.EnrolledDate = DateTime.Now;
@@ -294,14 +294,14 @@ namespace Disco.BI.DeviceBI
//if (RepoDeviceProfileContext.DistributionType == DeviceProfileConfiguration.DeviceProfileDistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne && RepoDevice.AssignedUser != null)
{
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.sAMAccountName, AssignedUserInfo.Domain, AssignedUserInfo.ObjectSid);
response.DeviceAssignedUserUsername = AssignedUserInfo.sAMAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
response.DeviceAssignedUserSID = AssignedUserInfo.ObjectSid;
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
}
response.DeviceComputerName = RepoDevice.ComputerName;
response.DeviceComputerName = RepoDevice.DeviceDomainId;
EnrolmentLog.LogSessionProgress(sessionId, 100, "Completed Successfully");
}
catch (EnrolSafeException ex)
@@ -321,44 +321,75 @@ namespace Disco.BI.DeviceBI
}
return response;
}
public static EnrolResponse Enrol(DiscoDataContext dbContext, string Username, Models.ClientServices.Enrol Request)
public static EnrolResponse Enrol(DiscoDataContext Database, string Username, Models.ClientServices.Enrol Request)
{
ActiveDirectoryMachineAccount MachineInfo = null;
ADMachineAccount adMachineAccount = null;
EnrolResponse response = new EnrolResponse();
User authenticatedUser = null;
AuthorizationToken authenticatedToken = null;
bool isAuthenticated = false;
ADDomain domain = null;
Lazy<ADDomainController> domainController = new Lazy<ADDomainController>(() =>
{
if (domain == null)
throw new InvalidOperationException("The [domain] variable must be initialized first");
return domain.GetAvailableDomainController(RequireWritable: true);
});
string sessionId = System.Guid.NewGuid().ToString("B");
response.SessionId = sessionId;
EnrolmentLog.LogSessionStarting(sessionId, Request.DeviceSerialNumber, EnrolmentTypes.Normal);
EnrolmentLog.LogSessionDeviceInfo(sessionId, Request);
try
{
EnrolmentLog.LogSessionProgress(sessionId, 10, "Loading User Data");
if (!string.IsNullOrWhiteSpace(Username))
{
authenticatedUser = UserBI.UserCache.GetUser(Username, dbContext);
isAuthenticated = (authenticatedUser != null);
authenticatedToken = UserService.GetAuthorization(Username, Database);
isAuthenticated = (authenticatedToken != null);
}
EnrolmentLog.LogSessionProgress(sessionId, 13, "Loading Device Data");
Device RepoDevice = dbContext.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
Device RepoDevice = Database.Devices.Include("AssignedUser").Include("DeviceModel").Include("DeviceProfile").Where(d => d.SerialNumber == Request.DeviceSerialNumber).FirstOrDefault();
EnrolmentLog.LogSessionProgress(sessionId, 15, "Discovering User/Device Disco Permissions");
if (isAuthenticated)
{
if (authenticatedUser.Type != "Admin")
if (!authenticatedToken.Has(Claims.Device.Actions.EnrolDevices))
{
if (authenticatedUser.Type != "Computer")
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1}; User Type: {2})", Request.DeviceSerialNumber, authenticatedUser.Id, authenticatedUser.Type));
if (!authenticatedUser.Id.Equals(string.Format("{0}$", Request.DeviceComputerName), System.StringComparison.InvariantCultureIgnoreCase))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1}; User Type: {2})", Request.DeviceSerialNumber, authenticatedUser.Id, authenticatedUser.Type));
if (!authenticatedToken.Has(Claims.ComputerAccount))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
if (!authenticatedToken.User.UserId.Equals(string.Format(@"{0}\{1}$", domain.NetBiosName, Request.DeviceComputerName), System.StringComparison.OrdinalIgnoreCase))
throw new EnrolSafeException(string.Format("Connection not correctly authenticated (SN: {0}; Auth User: {1})", Request.DeviceSerialNumber, authenticatedToken.User.UserId));
}
}
else
{
if (RepoDevice == null)
{
throw new EnrolSafeException(string.Format("Unknown Device Serial Number (SN: '{0}')", Request.DeviceSerialNumber));
}
if (!RepoDevice.AllowUnauthenticatedEnrol)
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
{
if (RepoDevice.DeviceProfile.AllowUntrustedReimageJobEnrolment)
{
if (Database.Jobs.Count(j => j.DeviceSerialNumber == RepoDevice.SerialNumber && j.JobTypeId == JobType.JobTypeIds.SImg && !j.ClosedDate.HasValue) == 0)
{
throw new EnrolSafeException(string.Format("Device has no open 'Software - Reimage' job (SN: '{0}')", Request.DeviceSerialNumber));
}
}
else
{
throw new EnrolSafeException(string.Format("Device isn't allowed an Unauthenticated Enrolment (SN: '{0}')", Request.DeviceSerialNumber));
}
}
}
if (Request.DeviceIsPartOfDomain && !string.IsNullOrWhiteSpace(Request.DeviceComputerName))
{
@@ -366,44 +397,59 @@ namespace Disco.BI.DeviceBI
System.Guid? uuidGuid = null;
System.Guid? macAddressGuid = null;
if (!string.IsNullOrEmpty(Request.DeviceUUID))
uuidGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(Request.DeviceUUID);
uuidGuid = ADMachineAccount.NetbootGUIDFromUUID(Request.DeviceUUID);
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
macAddressGuid = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
MachineInfo = ActiveDirectory.GetMachineAccount(Request.DeviceComputerName, uuidGuid, macAddressGuid);
macAddressGuid = ADMachineAccount.NetbootGUIDFromMACAddress(Request.DeviceLanMacAddress);
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
var requestDeviceId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName);
adMachineAccount = domainController.Value.RetrieveADMachineAccount(requestDeviceId, uuidGuid, macAddressGuid);
}
if (RepoDevice == null)
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "New Device, Creating Disco Instance");
EnrolmentLog.LogSessionTaskAddedDevice(sessionId, Request.DeviceSerialNumber);
DeviceProfile deviceProfile = dbContext.DeviceProfiles.Find(dbContext.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
DeviceProfile deviceProfile = Database.DeviceProfiles.Find(Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId);
var deviceModelResult = dbContext.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
else
EnrolmentLog.LogSessionDevice(sessionId, Request.DeviceSerialNumber, deviceModel.Id);
if (domain == null)
domain = ActiveDirectory.Context.GetDomainByName(Request.DeviceDNSDomainName);
RepoDevice = new Device
{
SerialNumber = Request.DeviceSerialNumber,
ComputerName = Request.DeviceComputerName,
DeviceDomainId = string.Format(@"{0}\{1}", domain.NetBiosName, Request.DeviceComputerName),
DeviceProfile = deviceProfile,
DeviceModel = deviceModel,
AllowUnauthenticatedEnrol = false,
CreatedDate = DateTime.Now,
EnrolledDate = DateTime.Now,
LastEnrolDate = DateTime.Now
LastEnrolDate = DateTime.Now,
DeviceDetails = new List<DeviceDetail>()
};
dbContext.Devices.Add(RepoDevice);
Database.Devices.Add(RepoDevice);
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
}
else
{
EnrolmentLog.LogSessionProgress(sessionId, 30, "Existing Device, Updating Disco Instance");
EnrolmentLog.LogSessionTaskUpdatingDevice(sessionId, Request.DeviceSerialNumber);
var deviceModelResult = dbContext.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModel.Trim());
var deviceModelResult = Database.DeviceModels.GetOrCreateDeviceModel(Request.DeviceManufacturer.Trim(), Request.DeviceModel.Trim(), Request.DeviceModelType.Trim());
DeviceModel deviceModel = deviceModelResult.Item1;
if (deviceModelResult.Item2)
EnrolmentLog.LogSessionTaskCreatedDeviceModel(sessionId, Request.DeviceSerialNumber, deviceModelResult.Item1.Manufacturer, deviceModelResult.Item1.Model);
@@ -412,90 +458,133 @@ namespace Disco.BI.DeviceBI
RepoDevice.DeviceModel = deviceModel;
if (!string.IsNullOrEmpty(Request.DeviceLanMacAddress))
RepoDevice.DeviceDetails.LanMacAddress(RepoDevice, Request.DeviceLanMacAddress);
if (!string.IsNullOrEmpty(Request.DeviceWlanMacAddress))
RepoDevice.DeviceDetails.WLanMacAddress(RepoDevice, Request.DeviceWlanMacAddress);
if (!RepoDevice.EnrolledDate.HasValue)
RepoDevice.EnrolledDate = DateTime.Now;
RepoDevice.LastEnrolDate = DateTime.Now;
}
if (MachineInfo == null)
if (adMachineAccount == null)
{
if (isAuthenticated || RepoDevice.AllowUnauthenticatedEnrol)
{
if (RepoDevice.DeviceProfile.ProvisionADAccount)
{
EnrolmentLog.LogSessionProgress(sessionId, 50, "Provisioning an Active Directory Computer Account");
if (string.IsNullOrEmpty(RepoDevice.ComputerName) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.ComputerName = RepoDevice.ComputerNameRender(dbContext);
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.ComputerName);
MachineInfo = ActiveDirectory.GetMachineAccount(RepoDevice.ComputerName);
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
if (domain == null)
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
if (string.IsNullOrEmpty(RepoDevice.DeviceDomainId) || RepoDevice.DeviceProfile.EnforceComputerNameConvention)
RepoDevice.DeviceDomainId = RepoDevice.ComputerNameRender(Database, domain);
string offlineProvisionDiagnosicInfo;
EnrolmentLog.LogSessionTaskProvisioningADAccount(sessionId, RepoDevice.SerialNumber, RepoDevice.DeviceDomainId);
adMachineAccount = domainController.Value.RetrieveADMachineAccount(RepoDevice.DeviceDomainId);
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
response.RequireReboot = true;
}
if (MachineInfo != null)
if (adMachineAccount != null)
{
response.DeviceComputerName = MachineInfo.Name;
response.DeviceDomainName = MachineInfo.Domain;
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
}
else
{
response.DeviceComputerName = RepoDevice.ComputerName;
response.DeviceDomainName = RepoDevice.ComputerName;
string accountUsername;
ADDomain accountDomain;
ActiveDirectory.ParseDomainAccountId(RepoDevice.DeviceDomainId, out accountUsername, out accountDomain);
response.DeviceDomainName = accountDomain == null ? null : accountDomain.NetBiosName;
response.DeviceComputerName = accountUsername;
}
}
else
{
RepoDevice.ComputerName = Request.DeviceComputerName;
response.DeviceComputerName = Request.DeviceComputerName;
response.DeviceDomainName = RepoDevice.ComputerName;
response.DeviceDomainName = Request.DeviceDNSDomainName;
}
}
else
{
RepoDevice.ComputerName = MachineInfo.Name;
response.DeviceComputerName = MachineInfo.Name;
response.DeviceDomainName = MachineInfo.Domain;
RepoDevice.DeviceDomainId = adMachineAccount.Id.Trim('$');
response.DeviceComputerName = adMachineAccount.Name;
response.DeviceDomainName = adMachineAccount.Domain.NetBiosName;
// Enforce Computer Name Convention
if (RepoDevice.DeviceProfile.EnforceComputerNameConvention)
if (!adMachineAccount.IsCriticalSystemObject && RepoDevice.DeviceProfile.EnforceComputerNameConvention)
{
var calculatedComputerName = RepoDevice.ComputerNameRender(dbContext);
if (!Request.DeviceComputerName.Equals(calculatedComputerName, StringComparison.InvariantCultureIgnoreCase))
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
throw new InvalidOperationException("No Organisational Unit has been set in the device profile");
if (domain == null)
domain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
var calculatedComputerName = RepoDevice.ComputerNameRender(Database, domain);
string calculatedAccountUsername;
ActiveDirectory.ParseDomainAccountId(calculatedComputerName, out calculatedAccountUsername);
if (!Request.DeviceComputerName.Equals(calculatedAccountUsername, StringComparison.OrdinalIgnoreCase))
{
EnrolmentLog.LogSessionProgress(sessionId, 50, string.Format("Renaming Device: {0} -> {1}", Request.DeviceComputerName, calculatedComputerName));
EnrolmentLog.LogSessionTaskRenamingDevice(sessionId, Request.DeviceComputerName, calculatedComputerName);
RepoDevice.ComputerName = calculatedComputerName;
response.DeviceComputerName = calculatedComputerName;
RepoDevice.DeviceDomainId = calculatedComputerName;
response.DeviceDomainName = domain.NetBiosName;
response.DeviceComputerName = calculatedAccountUsername;
// Create New Account
response.OfflineDomainJoin = ActiveDirectory.OfflineDomainJoinProvision(ref MachineInfo, RepoDevice.ComputerName, RepoDevice.DeviceProfile.OrganisationalUnit, sessionId);
string offlineProvisionDiagnosicInfo;
response.OfflineDomainJoin = domainController.Value.OfflineDomainJoinProvision(RepoDevice.DeviceDomainId, RepoDevice.DeviceProfile.OrganisationalUnit, ref adMachineAccount, out offlineProvisionDiagnosicInfo);
EnrolmentLog.LogSessionDiagnosticInformation(sessionId, offlineProvisionDiagnosicInfo);
response.RequireReboot = true;
}
}
// Enforce Organisation Unit
if (response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
// Enforce Organisational Unit
if (!adMachineAccount.IsCriticalSystemObject && response.OfflineDomainJoin == null && RepoDevice.DeviceProfile.EnforceOrganisationalUnit)
{
if ((RepoDevice.DeviceProfile.OrganisationalUnit == null && MachineInfo.ParentDistinguishedName.Equals("CN=Computers", StringComparison.InvariantCultureIgnoreCase)) // Null (Default) OU
|| !MachineInfo.ParentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.InvariantCultureIgnoreCase)) // Custom OU
{
string newOU = RepoDevice.DeviceProfile.OrganisationalUnit ?? "CN=Computers";
var parentDistinguishedName = adMachineAccount.ParentDistinguishedName;
if (string.IsNullOrWhiteSpace(RepoDevice.DeviceProfile.OrganisationalUnit))
throw new InvalidOperationException(string.Format("The Organisational Unit for the Device Profile '{0}' [{1}] is not set.", RepoDevice.DeviceProfile.Name, RepoDevice.DeviceProfile.Id));
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisation Unit: {0} -> {1}", MachineInfo.ParentDistinguishedName, newOU));
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, MachineInfo.ParentDistinguishedName, newOU);
MachineInfo.MoveOrganisationUnit(RepoDevice.DeviceProfile.OrganisationalUnit);
MachineInfo = ActiveDirectory.GetMachineAccount(MachineInfo.sAMAccountName);
if (!parentDistinguishedName.Equals(RepoDevice.DeviceProfile.OrganisationalUnit, StringComparison.OrdinalIgnoreCase)) // Custom OU
{
var proposedDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(RepoDevice.DeviceProfile.OrganisationalUnit);
var currentDomain = ActiveDirectory.Context.GetDomainFromDistinguishedName(parentDistinguishedName);
if (currentDomain != proposedDomain)
throw new NotSupportedException("Unable to move the devices organisational unit when the source and destination domains are different.");
if (domain == null)
domain = proposedDomain;
else if (domain != proposedDomain)
throw new NotSupportedException("To many domains involved in this enrolment, contact support regarding your scenario.");
EnrolmentLog.LogSessionProgress(sessionId, 65, string.Format("Moving Device Organisational Unit: {0} -> {1}", parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit));
EnrolmentLog.LogSessionTaskMovingDeviceOrganisationUnit(sessionId, parentDistinguishedName, RepoDevice.DeviceProfile.OrganisationalUnit);
adMachineAccount.MoveOrganisationalUnit(domainController.Value, RepoDevice.DeviceProfile.OrganisationalUnit);
response.RequireReboot = true;
}
}
}
if (MachineInfo != null)
if (adMachineAccount != null && !adMachineAccount.IsCriticalSystemObject)
{
EnrolmentLog.LogSessionProgress(sessionId, 75, "Updating Active Directory Computer Account Properties");
MachineInfo.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
adMachineAccount.UpdateNetbootGUID(Request.DeviceUUID, Request.DeviceLanMacAddress);
if (RepoDevice.AssignedUser != null)
MachineInfo.SetDescription(RepoDevice);
adMachineAccount.SetDescription(RepoDevice);
}
if (RepoDevice.DeviceProfile.DistributionType == DeviceProfile.DistributionTypes.OneToOne)
{
@@ -506,13 +595,14 @@ namespace Disco.BI.DeviceBI
else
{
EnrolmentLog.LogSessionProgress(sessionId, 80, "Retrieving Active Directory Assigned User Account");
ActiveDirectoryUserAccount AssignedUserInfo = ActiveDirectory.GetUserAccount(RepoDevice.AssignedUser.Id);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.sAMAccountName, AssignedUserInfo.Domain, AssignedUserInfo.ObjectSid);
ADUserAccount AssignedUserInfo = ActiveDirectory.RetrieveADUserAccount(RepoDevice.AssignedUser.UserId);
EnrolmentLog.LogSessionTaskAssigningUser(sessionId, RepoDevice.SerialNumber, AssignedUserInfo.DisplayName, AssignedUserInfo.SamAccountName, AssignedUserInfo.Domain.NetBiosName, AssignedUserInfo.SecurityIdentifier.ToString());
response.AllowBootstrapperUninstall = true;
response.DeviceAssignedUserUsername = AssignedUserInfo.sAMAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain;
response.DeviceAssignedUserIsLocalAdmin = RepoDevice.DeviceProfile.AssignedUserLocalAdmin;
response.DeviceAssignedUserUsername = AssignedUserInfo.SamAccountName;
response.DeviceAssignedUserDomain = AssignedUserInfo.Domain.NetBiosName;
response.DeviceAssignedUserName = AssignedUserInfo.DisplayName;
response.DeviceAssignedUserSID = AssignedUserInfo.ObjectSid;
response.DeviceAssignedUserSID = AssignedUserInfo.SecurityIdentifier.ToString();
}
}
else
@@ -523,7 +613,7 @@ namespace Disco.BI.DeviceBI
{
EnrolmentLog.LogSessionProgress(sessionId, 90, "Provisioning a Wireless Certificate");
var allocationResult = RepoDevice.AllocateCertificate(dbContext);
var allocationResult = RepoDevice.AllocateCertificate(Database);
var deviceCertificate = allocationResult.Item1;
if (deviceCertificate != null)
{
@@ -575,4 +665,4 @@ namespace Disco.BI.DeviceBI
return response;
}
}
}
}
-102
View File
@@ -1,102 +0,0 @@
using Disco.Models.BI.Device;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.DeviceBI.Importing
{
public static class Export
{
private const string ExportHeader = "Serial Number,Device Model,Device Profile,Device Batch,Assigned User,Location,Asset Number";
public static MemoryStream GenerateExport(IQueryable<Device> Devices)
{
var devices = Devices.Select(d => new ImportDevice()
{
SerialNumber = d.SerialNumber,
DeviceModelId = d.DeviceModelId,
DeviceProfileId = d.DeviceProfileId,
DeviceBatchId = d.DeviceBatchId,
AssignedUserId = d.AssignedUserId,
Location = d.Location,
AssetNumber = d.AssetNumber
});
MemoryStream exportStream = new MemoryStream();
StreamWriter exportWriter = new StreamWriter(exportStream);
// Write Header
exportWriter.WriteLine(ExportHeader);
foreach (var device in devices)
device.ExportCsv(exportWriter);
exportWriter.Flush();
exportStream.Position = 0;
return exportStream;
}
private static void ExportCsv(this ImportDevice device, StreamWriter writer)
{
// SERIAL NUMBER
writer.Write('"');
writer.Write(device.SerialNumber.Replace("\"", "\"\""));
writer.Write('"');
writer.Write(',');
// DEVICE MODEL
if (device.DeviceModelId.HasValue)
writer.Write(device.DeviceModelId.Value);
writer.Write(',');
// DEVICE PROFILE
writer.Write(device.DeviceProfileId);
writer.Write(',');
// DEVICE BATCH
if (device.DeviceBatchId.HasValue)
writer.Write(device.DeviceBatchId.Value);
writer.Write(',');
// ASSIGNED USER
if (device.AssignedUserId != null)
{
writer.Write('"');
writer.Write(device.AssignedUserId.Replace("\"", "\"\""));
writer.Write('"');
}
writer.Write(',');
// LOCATION
if (!string.IsNullOrWhiteSpace(device.Location))
{
writer.Write('"');
writer.Write(device.Location.Replace("\"", "\"\""));
writer.Write('"');
}
writer.Write(',');
// ASSET NUMBER
if (!string.IsNullOrWhiteSpace(device.AssetNumber))
{
writer.Write('"');
writer.Write(device.AssetNumber.Replace("\"", "\"\""));
writer.Write('"');
}
writer.WriteLine();
}
}
}
-265
View File
@@ -1,265 +0,0 @@
using Disco.BI.Extensions;
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using PopulateRecordReferences = System.Tuple<System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceModel>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceProfile>, System.Collections.Generic.Dictionary<int, Disco.Models.Repository.DeviceBatch>>;
namespace Disco.BI.DeviceBI.Importing
{
public static class Import
{
internal const string ImportParseCacheKey = "ImportParseResults_{0}";
public static ImportDeviceSession GetSession(string ImportParseTaskId)
{
string parseKey = string.Format(ImportParseCacheKey, ImportParseTaskId);
return (ImportDeviceSession)HttpRuntime.Cache.Get(parseKey);
}
internal static bool ImportRecord(this ImportDevice device, DiscoDataContext dbContext, PopulateRecordReferences references)
{
// Skips If Errors
if (device.Errors == null || device.Errors.Count == 0)
{
// Re-Populate & Skip If Errors
device.PopulateRecord(dbContext, references);
if (device.Errors == null || device.Errors.Count == 0)
{
Device discoDevice = device.Device;
if (discoDevice == null)
{
// New Device
discoDevice = new Device()
{
SerialNumber = device.SerialNumber.ToUpper(),
CreatedDate = DateTime.Now,
AllowUnauthenticatedEnrol = true,
};
dbContext.Devices.Add(discoDevice);
}
if (discoDevice.DeviceModelId != device.DeviceModelId)
discoDevice.DeviceModelId = device.DeviceModelId;
if (discoDevice.DeviceProfileId != device.DeviceProfileId)
discoDevice.DeviceProfileId = device.DeviceProfileId;
if (discoDevice.DeviceBatchId != device.DeviceBatchId)
discoDevice.DeviceBatchId = device.DeviceBatchId;
if (discoDevice.Location != device.Location)
discoDevice.Location = device.Location;
if (discoDevice.AssetNumber != device.AssetNumber)
discoDevice.AssetNumber = device.AssetNumber;
if (discoDevice.AssignedUserId != device.AssignedUserId)
{
discoDevice.AssignDevice(dbContext, device.AssignedUser);
}
dbContext.SaveChanges();
return true;
}
}
return false;
}
internal static PopulateRecordReferences GetPopulateRecordReferences(DiscoDataContext dbContext)
{
return new PopulateRecordReferences(
dbContext.DeviceModels.ToDictionary(dm => dm.Id),
dbContext.DeviceProfiles.ToDictionary(dp => dp.Id),
dbContext.DeviceBatches.ToDictionary(db => db.Id)
);
}
internal static void PopulateRecord(this ImportDevice device, DiscoDataContext dbContext, PopulateRecordReferences references)
{
var deviceModels = references.Item1;
var deviceProfiles = references.Item2;
var deviceBatches = references.Item3;
// SERIAL NUMBER - Existing Device
if (!device.Errors.ContainsKey("SerialNumber"))
{
device.Device = dbContext.Devices.Find(device.SerialNumber);
if (device.Device != null && device.Device.DecommissionedDate.HasValue)
device.Errors.Add("SerialNumber", "The device is decommissioned");
}
// DEVICE MODEL
if (!device.Errors.ContainsKey("DeviceModelId"))
{
DeviceModel deviceModel;
if (!device.DeviceModelId.HasValue)
device.DeviceModelId = 1; // Default 'Unknown Device Model'
if (!deviceModels.TryGetValue(device.DeviceModelId.Value, out deviceModel))
device.Errors.Add("DeviceModelId", string.Format("Unknown device model id: {0}", device.DeviceModelId));
else
device.DeviceModel = deviceModel;
}
// DEVICE PROFILE
if (!device.Errors.ContainsKey("DeviceProfileId"))
{
DeviceProfile deviceProfile;
if (!deviceProfiles.TryGetValue(device.DeviceProfileId, out deviceProfile))
device.Errors.Add("DeviceProfileId", string.Format("Unknown device profile id: {0}", device.DeviceProfileId));
else
device.DeviceProfile = deviceProfile;
}
// DEVICE BATCH
if (!device.Errors.ContainsKey("DeviceBatchId") && device.DeviceBatchId.HasValue)
{
DeviceBatch deviceBatch;
if (!deviceBatches.TryGetValue(device.DeviceBatchId.Value, out deviceBatch))
device.Errors.Add("DeviceBatchId", string.Format("Unknown device Batch id: {0}", device.DeviceBatchId));
else
device.DeviceBatch = deviceBatch;
}
// ASSIGNED USER
if (!device.Errors.ContainsKey("AssignedUserId") && device.AssignedUserId != null)
{
try
{
device.AssignedUser = UserBI.UserCache.GetUser(device.AssignedUserId, dbContext, true);
}
catch (ArgumentException)
{
device.Errors.Add("AssignedUserId", string.Format("Unknown user id: {0}", device.AssignedUserId));
}
}
}
internal static ImportDevice ParseRecord(this string[] record)
{
int csvFieldCount = record.Length;
if (csvFieldCount < 1)
throw new ArgumentException("At least one CSV field is required (Serial Number)");
string csvSerialNumber;
string csvDeviceModelId;
int deviceModelId = 1; // Default 'Unknown Device Model'
string csvDeviceProfileId;
int deviceProfileId = 1; // 'Default' Profile
string csvDeviceBatchId;
int deviceBatchId = 0; // No Batch
string csvAssignedUserId = null;
string csvLocation = null;
string csvAssetNumber = null;
Dictionary<string, string> errors = new Dictionary<string, string>();
// SERIAL NUMBER
csvSerialNumber = record[0];
if (string.IsNullOrWhiteSpace(csvSerialNumber))
errors.Add("SerialNumber", "The serial number is required");
else if (csvSerialNumber.Trim().Length > 60)
errors.Add("SerialNumber", "The serial number must be less than or equal to 60 characters");
if (csvFieldCount > 1)
{
// DEVICE MODEL
csvDeviceModelId = record[1];
if (!string.IsNullOrWhiteSpace(csvDeviceModelId))
if (!int.TryParse(csvDeviceModelId, out deviceModelId))
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be a number");
else if (deviceModelId < 1)
errors.Add("DeviceModelId", "The device model is optional, but when supplied must be greater than 0");
if (csvFieldCount > 2)
{
// DEVICE PROFILE
csvDeviceProfileId = record[2];
if (!string.IsNullOrWhiteSpace(csvDeviceProfileId))
if (!int.TryParse(csvDeviceProfileId, out deviceProfileId))
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be a number");
else if (deviceProfileId < 1)
errors.Add("DeviceProfileId", "The device profile is optional, but when supplied must be greater than 0");
if (csvFieldCount > 3)
{
// DEVICE BATCH
csvDeviceBatchId = record[3];
if (!string.IsNullOrWhiteSpace(csvDeviceBatchId))
if (!int.TryParse(csvDeviceBatchId, out deviceBatchId))
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be a number");
else if (deviceBatchId < 1)
errors.Add("DeviceBatchId", "The device batch is optional, but when supplied must be greater than 0");
if (csvFieldCount > 4)
{
// ASSIGNED USER
csvAssignedUserId = record[4];
if (string.IsNullOrWhiteSpace(csvAssignedUserId))
csvAssignedUserId = null; // Not Assigned
else if (csvAssignedUserId.Length > 50)
errors.Add("AssignedUserId", "The assigned user must be less than or equal to 50 characters");
if (csvFieldCount > 5)
{
// LOCATION
csvLocation = record[5];
if (string.IsNullOrWhiteSpace(csvLocation))
csvLocation = null; // No Location Specified
else if (csvLocation.Length > 250)
errors.Add("Location", "The location must be less than or equal to 250 characters");
if (csvFieldCount > 6)
{
// ASSET NUMBER
csvAssetNumber = record[6];
if (string.IsNullOrWhiteSpace(csvAssetNumber))
csvAssetNumber = null; // No Location Specified
else if (csvAssetNumber.Length > 40)
errors.Add("AssetNumber", "The asset number must be less than or equal to 40 characters");
}
}
}
}
}
}
return new ImportDevice()
{
SerialNumber = csvSerialNumber.Trim(),
DeviceModelId = deviceModelId,
DeviceProfileId = deviceProfileId,
DeviceBatchId = deviceBatchId == 0 ? (int?)null : deviceBatchId,
AssignedUserId = csvAssignedUserId,
Location = csvLocation,
AssetNumber = csvAssetNumber,
Errors = errors
};
}
#region ImportDevice Extensions
public static string ImportStatus(this ImportDevice device)
{
if (device.Errors.Count > 0)
return "Error";
if (device.Device != null)
return "Update";
return "New";
}
#endregion
}
}
@@ -1,91 +0,0 @@
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Models.Repository;
using Disco.Services.Tasks;
using LumenWorks.Framework.IO.Csv;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;
namespace Disco.BI.DeviceBI.Importing
{
public class ImportParseTask : ScheduledTask
{
public override string TaskName { get { return "Import Devices - Parsing"; } }
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
protected override void ExecuteTask()
{
string csvFilename = (string)this.ExecutionContext.JobDetail.JobDataMap["CsvFilename"];
MemoryStream csvStream = (MemoryStream)this.ExecutionContext.JobDetail.JobDataMap["CsvImport"];
this.Status.UpdateStatus(0, "Parsing CSV File", "Loading Records");
List<ImportDevice> records;
using (TextReader csvTextReader = new StreamReader(csvStream))
{
using (CsvReader csvReader = new CsvReader(csvTextReader, true))
{
csvReader.DefaultParseErrorAction = ParseErrorAction.ThrowException;
csvReader.MissingFieldAction = MissingFieldAction.ReplaceByNull;
records = csvReader.Select(record => record.ParseRecord()).ToList();
}
}
csvStream.Dispose();
this.Status.UpdateStatus(20, "Parsing CSV File", string.Format("Linking {0} Records", records.Count));
using (DiscoDataContext dbContext = new DiscoDataContext())
{
var populateReferences = Import.GetPopulateRecordReferences(dbContext);
DateTime lastUpdate = DateTime.Now;
foreach (var record in records)
{
record.PopulateRecord(dbContext, populateReferences);
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
{
// Update every second
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 80)));
lastUpdate = DateTime.Now;
}
}
}
// Create Session Result
ImportDeviceSession session = new ImportDeviceSession()
{
ImportParseTaskId = this.Status.SessionId,
ImportFilename = csvFilename,
ImportDevices = records
};
// Set Results to Cache
string key = string.Format(Import.ImportParseCacheKey, this.Status.SessionId);
HttpRuntime.Cache.Insert(key, session, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(60), CacheItemPriority.NotRemovable, null);
}
public static ScheduledTaskStatus Run(Stream CsvImport, String CsvFilename)
{
MemoryStream csvStream = new MemoryStream();
CsvImport.CopyTo(csvStream);
csvStream.Position = 0;
var task = new ImportParseTask();
JobDataMap taskData = new JobDataMap() { { "CsvImport", csvStream }, { "CsvFilename", CsvFilename } };
return task.ScheduleTask(taskData);
}
}
}
@@ -1,70 +0,0 @@
using Disco.Data.Repository;
using Disco.Models.BI.Device;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Disco.BI.DeviceBI.Importing
{
public class ImportProcessTask : ScheduledTask
{
public override string TaskName { get { return "Import Devices - Processing Changes"; } }
public override bool SingleInstanceTask { get { return false; } }
public override bool CancelInitiallySupported { get { return false; } }
protected override void ExecuteTask()
{
string importParseTaskId = (string)this.ExecutionContext.JobDetail.JobDataMap["ImportParseTaskId"];
if (string.IsNullOrWhiteSpace(importParseTaskId))
throw new ArgumentNullException("ImportParseTaskId");
ImportDeviceSession session = Import.GetSession(importParseTaskId);
if (session == null)
throw new InvalidOperationException("The session timed out (60 minutes), try importing again");
List<ImportDevice> records = session.ImportDevices;
int recordsImported = 0;
this.Status.UpdateStatus(0, "Processing Device Import", "Importing Devices");
using (DiscoDataContext dbContext = new DiscoDataContext())
{
var populateReferences = Import.GetPopulateRecordReferences(dbContext);
DateTime lastUpdate = DateTime.Now;
foreach (var record in records)
{
if (record.ImportRecord(dbContext, populateReferences))
recordsImported++;
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > 1)
{
// Update every second
this.Status.UpdateStatus((int)Math.Floor((((double)(records.IndexOf(record) + 1) / records.Count) * 100)), string.Format("Importing: {0} ({1} of {2})", record.SerialNumber, records.IndexOf(record) + 1, records.Count));
lastUpdate = DateTime.Now;
}
}
}
this.Status.SetFinishedMessage(string.Format("Imported {0} of {1} Devices", recordsImported, records.Count));
}
public static ScheduledTaskStatus Run(string ImportParseTaskId)
{
if (string.IsNullOrWhiteSpace(ImportParseTaskId))
throw new ArgumentNullException("ImportParseTaskId");
var task = new ImportProcessTask();
JobDataMap taskData = new JobDataMap() { { "ImportParseTaskId", ImportParseTaskId } };
return task.ScheduleTask(taskData);
}
}
}
@@ -0,0 +1,123 @@
using Disco.BI.Extensions;
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.DeviceBI.Migration
{
public class LogMacAddressImporting : ScheduledTask
{
public override string TaskName { get { return "Migration: Logs to Device Mac Address Details"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
#region Required Helpers
private static string RequiredFilePath(DiscoDataContext Database)
{
if (Database.DiscoConfiguration.DataStoreLocation != null)
return System.IO.Path.Combine(Database.DiscoConfiguration.DataStoreLocation, "_LogMacAddressImportingRequired.txt");
else
return null;
}
public static bool IsRequired(DiscoDataContext Database)
{
var requiredFilePath = RequiredFilePath(Database);
if (requiredFilePath == null)
return false;
else
return System.IO.File.Exists(requiredFilePath);
}
public static void SetRequired(DiscoDataContext Database)
{
var requiredFilePath = RequiredFilePath(Database);
if (requiredFilePath != null)
{
System.IO.File.WriteAllText(requiredFilePath, "This file exists to indicate an Importing of Mac Address from the Disco Logs is required. It will automatically be deleted when the import completes.");
System.IO.File.SetAttributes(requiredFilePath, System.IO.FileAttributes.Hidden);
}
// ELSE: Could never be required if no DataStoreLocation is set (no logs to process)
}
#endregion
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
if (IsRequired(Database))
{
// Schedule in 15mins
var trigger = TriggerBuilder.Create()
.StartAt(DateTimeOffset.Now.AddMinutes(5));
this.ScheduleTask(trigger);
}
}
public static ScheduledTaskStatus ScheduleImmediately()
{
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(LogMacAddressImporting)).Where(s => s.IsRunning).FirstOrDefault();
if (existingTask != null)
return existingTask;
var instance = new LogMacAddressImporting();
return instance.ScheduleTask();
}
protected override void ExecuteTask()
{
using (DiscoDataContext database = new DiscoDataContext())
{
Status.UpdateStatus(0, "Importing MAC Addresses", "Querying Logs for Details");
// Load Logs
var logRetriever = new ReadLogContext()
{
Module = DeviceBI.EnrolmentLog.Current.ModuleId,
EventTypes = new List<int>() { (int)DeviceBI.EnrolmentLog.EventTypeIds.SessionDeviceInfo }
};
var results = logRetriever.Query(database);
Status.UpdateStatus(50, string.Format("Passing {0} logs", results.Count));
Dictionary<string, Tuple<string, string>> addresses = new Dictionary<string, Tuple<string, string>>();
foreach (var result in results.OrderBy(r => r.Timestamp))
addresses[((string)result.Arguments[1]).ToLower()] = new Tuple<string, string>((string)result.Arguments[4], (string)result.Arguments[5]);
Status.UpdateStatus(75, string.Format("Importing {0} details", addresses.Count));
var devices = database.Devices.Include("DeviceDetails").ToList();
Tuple<string, string> addressResult;
foreach (var device in devices)
{
if (addresses.TryGetValue(device.SerialNumber.ToLower(), out addressResult))
{
if (!string.IsNullOrEmpty(addressResult.Item1))
device.DeviceDetails.LanMacAddress(device, addressResult.Item1);
if (!string.IsNullOrEmpty(addressResult.Item2))
device.DeviceDetails.WLanMacAddress(device, addressResult.Item2);
}
}
Status.UpdateStatus(90, "Saving to Database");
database.SaveChanges();
// Finished - Remove Placeholder File
var requiredFilePath = RequiredFilePath(database);
if (System.IO.File.Exists(requiredFilePath))
System.IO.File.Delete(requiredFilePath);
}
}
}
}
-56
View File
@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Search;
using Disco.Models.Repository;
using Disco.Data.Repository;
namespace Disco.BI.DeviceBI
{
public static class Searching
{
private static List<DeviceSearchResultItem> Search_SelectDeviceSearchResultItem(IQueryable<Device> Query, int? LimitCount = null){
if (LimitCount.HasValue)
Query = Query.Take(LimitCount.Value);
return Query.Select(d => new DeviceSearchResultItem()
{
SerialNumber = d.SerialNumber,
AssetNumber = d.AssetNumber,
ComputerName = d.ComputerName,
DeviceModelDescription = d.DeviceModel.Description,
DeviceProfileDescription = d.DeviceProfile.Description,
DecommissionedDate = d.DecommissionedDate,
AssignedUserId = d.AssignedUserId,
AssignedUserDisplayName = d.AssignedUser.DisplayName,
JobCount = d.Jobs.Count()
}).ToList();
}
public static List<DeviceSearchResultItem> Search(DiscoDataContext dbContext, string Term, int? LimitCount = null)
{
return Search_SelectDeviceSearchResultItem(dbContext.Devices.Where(d =>
d.AssetNumber.Contains(Term) ||
d.ComputerName.Contains(Term) ||
d.SerialNumber.Contains(Term) ||
d.Location.Contains(Term) ||
Term.Contains(d.SerialNumber)
), LimitCount);
}
public static List<DeviceSearchResultItem> SearchDeviceModel(DiscoDataContext dbContext, int DeviceModelId, int? LimitCount = null)
{
return Search_SelectDeviceSearchResultItem(dbContext.Devices.Where(d => d.DeviceModelId == DeviceModelId), LimitCount);
}
public static List<DeviceSearchResultItem> SearchDeviceProfile(DiscoDataContext dbContext, int DeviceProfileId, int? LimitCount = null)
{
return Search_SelectDeviceSearchResultItem(dbContext.Devices.Where(d => d.DeviceProfileId == DeviceProfileId), LimitCount);
}
public static List<DeviceSearchResultItem> SearchDeviceBatch(DiscoDataContext dbContext, int DeviceBatchId, int? LimitCount = null)
{
return Search_SelectDeviceSearchResultItem(dbContext.Devices.Where(d => d.DeviceBatchId == DeviceBatchId), LimitCount);
}
}
}
@@ -16,7 +16,7 @@ namespace Disco.BI.DocumentTemplateBI
{
private static ConcurrentDictionary<string, List<RectangleF>> _Cache = new ConcurrentDictionary<string, List<RectangleF>>();
public static List<RectangleF> GetLocations(DocumentTemplate dt, DiscoDataContext dbContext)
public static List<RectangleF> GetLocations(DocumentTemplate dt, DiscoDataContext Database)
{
// Check Cache
List<RectangleF> locations;
@@ -25,7 +25,7 @@ namespace Disco.BI.DocumentTemplateBI
return locations;
}
// Generate Cache
return GenerateLocations(dt, dbContext);
return GenerateLocations(dt, Database);
}
public static bool InvalidateLocations(DocumentTemplate dt)
@@ -47,9 +47,9 @@ namespace Disco.BI.DocumentTemplateBI
return _Cache.TryAdd(DocumentTemplateId, Locations);
}
internal static List<RectangleF> GenerateLocations(DocumentTemplate dt, DiscoDataContext dbContext)
internal static List<RectangleF> GenerateLocations(DocumentTemplate dt, DiscoDataContext Database)
{
string templateFilename = dt.RepositoryFilename(dbContext);
string templateFilename = dt.RepositoryFilename(Database);
PdfReader pdfReader = new PdfReader(templateFilename);
List<RectangleF> locations = new List<RectangleF>();
@@ -1,5 +1,6 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Interop.ActiveDirectory;
using System;
namespace Disco.BI.DocumentTemplateBI
{
@@ -61,14 +62,14 @@ namespace Disco.BI.DocumentTemplateBI
public string DataScope { get; private set; }
public static bool IsDocumentUniqueIdentifier(string UniqueIdentifier)
{
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.InvariantCultureIgnoreCase);
return UniqueIdentifier.StartsWith("Disco|", System.StringComparison.OrdinalIgnoreCase);
}
public DocumentUniqueIdentifier(string TemplateTypeId, string DataId, string CreatorId, DateTime TimeStamp, int? Page = null, string Tag = null)
{
this.Tag = Tag;
this.TemplateTypeId = TemplateTypeId;
this.DataId = DataId;
this.CreatorId = CreatorId;
this.CreatorId = ActiveDirectory.ParseDomainAccountId(CreatorId);
this.TimeStamp = TimeStamp;
this.Page = Page ?? 0;
}
@@ -93,7 +94,7 @@ namespace Disco.BI.DocumentTemplateBI
}
if (s.Length >= 5)
{
this.CreatorId = s[4];
this.CreatorId = ActiveDirectory.ParseDomainAccountId(s[4]);
}
if (s.Length >= 6)
{
@@ -115,7 +116,7 @@ namespace Disco.BI.DocumentTemplateBI
}
throw new System.ArgumentException(string.Format("Invalid Document Unique Identifier Version ({0})", s[1]), "UniqueIdentifier");
}
public bool LoadComponents(DiscoDataContext Context)
public bool LoadComponents(DiscoDataContext Database)
{
bool LoadComponents;
if (!this._loadedComponentsOk.HasValue)
@@ -142,7 +143,7 @@ namespace Disco.BI.DocumentTemplateBI
}
else
{
this._documentTemplate = Context.DocumentTemplates.Find(this.TemplateTypeId);
this._documentTemplate = Database.DocumentTemplates.Find(this.TemplateTypeId);
if (this._documentTemplate != null)
{
scopeType = this._documentTemplate.Scope;
@@ -158,7 +159,7 @@ namespace Disco.BI.DocumentTemplateBI
switch (scopeType)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
Device d = Context.Devices.Find(this.DataId);
Device d = Database.Devices.Find(this.DataId);
if (d != null)
{
this._data = d;
@@ -169,7 +170,7 @@ namespace Disco.BI.DocumentTemplateBI
}
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
Job i = Context.Jobs.Find(int.Parse(this.DataId));
Job i = Database.Jobs.Find(int.Parse(this.DataId));
if (i != null)
{
this._data = i;
@@ -180,7 +181,7 @@ namespace Disco.BI.DocumentTemplateBI
}
break;
case DocumentTemplate.DocumentTemplateScopes.User:
User u = Context.Users.Find(this.DataId);
User u = Database.Users.Find(ActiveDirectory.ParseDomainAccountId(this.DataId));
if (u != null)
{
this._data = u;
@@ -16,15 +16,15 @@ namespace Disco.BI.DocumentTemplateBI.Importer
public const string WatcherFilter = "*.pdf";
public string DropBoxLocation { get; private set; }
public DocumentDropBoxMonitor(DiscoDataContext Context, ISchedulerFactory SchedulerFactory, Cache HttpCache)
public DocumentDropBoxMonitor(DiscoDataContext Database, ISchedulerFactory SchedulerFactory, Cache HttpCache)
{
if (Context == null)
if (Database == null)
throw new System.ArgumentNullException("Context");
this._httpCache = HttpCache;
var location = DataStore.CreateLocation(Context, "DocumentDropBox");
var location = DataStore.CreateLocation(Database, "DocumentDropBox");
this.DropBoxLocation = location.EndsWith(@"\") ? location : string.Concat(location, @"\");
this._scheduler = SchedulerFactory.GetScheduler();
@@ -12,8 +12,9 @@ namespace Disco.BI.DocumentTemplateBI.Importer
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
public override bool LogExceptionsOnly { get { return true; } }
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Trigger Daily @ 12:30am
TriggerBuilder triggerBuilder = TriggerBuilder.Create().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 30));
@@ -24,9 +25,9 @@ namespace Disco.BI.DocumentTemplateBI.Importer
protected override void ExecuteTask()
{
string dataStoreLocation;
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
dataStoreLocation = DataStore.CreateLocation(dbContext, "Cache\\DocumentDropBox_SessionPages");
dataStoreLocation = DataStore.CreateLocation(database, "Cache\\DocumentDropBox_SessionPages");
}
int deleteCount = 0;
@@ -40,12 +40,12 @@ namespace Disco.BI.DocumentTemplateBI.Importer
try
{
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
if (retryCount < 18)
{
context.JobDetail.JobDataMap["RetryCount"] = (++retryCount);
bool processResult = Interop.Pdf.PdfImporter.ProcessPdfAttachment(filename, dbContext, sessionId, httpCache);
bool processResult = Interop.Pdf.PdfImporter.ProcessPdfAttachment(filename, database, sessionId, httpCache);
if (processResult)
{
@@ -60,7 +60,7 @@ namespace Disco.BI.DocumentTemplateBI.Importer
{
try
{
string folderError = DataStore.CreateLocation(dbContext, "DocumentDropBox_Errors");
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
int filenameErrorCount = 0;
while (File.Exists(filenameError))
@@ -85,7 +85,7 @@ namespace Disco.BI.DocumentTemplateBI.Importer
{
try
{
string folderError = DataStore.CreateLocation(dbContext, "DocumentDropBox_Errors");
string folderError = DataStore.CreateLocation(database, "DocumentDropBox_Errors");
string filenameError = Path.Combine(folderError, Path.GetFileName(filename));
int filenameErrorCount = 0;
while (File.Exists(filenameError))
@@ -0,0 +1,486 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
{
public class DocumentTemplateDevicesManagedGroup : ADManagedGroup
{
private const string KeyFormat = "DocumentTemplate_{0}_Devices";
private const string DeviceDescriptionFormat = "Devices with a {0} attachment will be added to this Active Directory group.";
private const string DescriptionFormat = "{0}s with a {1} attachment will have any associated devices added to this Active Directory group.";
private const string CategoryDescriptionFormat = "Related Devices Linked Group";
private const string GroupDescriptionFormat = "{0} [Document Template Devices]";
private IDisposable repositoryAddSubscription;
private IDisposable repositoryRemoveSubscription;
private IDisposable deviceRenameRepositorySubscription;
private IDisposable jobCloseRepositorySubscription;
private IDisposable deviceAssignmentRepositorySubscription;
private string DocumentTemplateId;
private string DocumentTemplateDescription;
private string DocumentTemplateScope;
public override string Description { get { return GetDescription(DocumentTemplateScope, DocumentTemplateDescription); } }
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, DocumentTemplateDescription); } }
public override bool IncludeFilterBeginDate { get { return true; } }
private DocumentTemplateDevicesManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DocumentTemplate DocumentTemplate)
: base(Key, Configuration)
{
this.DocumentTemplateId = DocumentTemplate.Id;
this.DocumentTemplateDescription = DocumentTemplate.Description;
this.DocumentTemplateScope = DocumentTemplate.Scope;
}
public override void Initialize()
{
// Subscribe to changes
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
// Observe Device Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value
.Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessDeviceAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessDeviceAttachmentRemoveEvent);
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
// Observe Job Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.JobAttachmentAddRepositoryEvents.Value
.Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessJobAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessJobAttachmentRemoveEvent);
// Observe Job Close/Reopen
jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value
.Subscribe(ProcessJobCloseRepositoryEvent);
break;
case DocumentTemplate.DocumentTemplateScopes.User:
// Observe User Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
.Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessUserAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessUserAttachmentRemoveEvent);
// Observe Device Assignments
deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value
.Subscribe(ProcessDeviceAssignmentRepositoryEvent);
break;
}
// Observe Device Renaming (DeviceDomainId)
deviceRenameRepositorySubscription = DocumentTemplateManagedGroups.DeviceRenameRepositoryEvents.Value
.Subscribe(ProcessDeviceRenameRepositoryEvent);
}
public static string GetKey(DocumentTemplate DocumentTemplate)
{
return string.Format(KeyFormat, DocumentTemplate.Id);
}
private static string GetDescription(string DocumentTemplateScope, string DocumentTemplateDescription)
{
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
return string.Format(DeviceDescriptionFormat, DocumentTemplateDescription);
case DocumentTemplate.DocumentTemplateScopes.Job:
case DocumentTemplate.DocumentTemplateScopes.User:
return string.Format(DescriptionFormat, DocumentTemplateScope, DocumentTemplateDescription);
default:
throw new ArgumentException("Unknown Document Template Scope", "Scope");
}
}
public static string GetDescription(DocumentTemplate DocumentTemplate)
{
return GetDescription(DocumentTemplate.Scope, DocumentTemplate.Description);
}
public static string GetCategoryDescription(DocumentTemplate DocumentTemplate)
{
return CategoryDescriptionFormat;
}
public static bool TryGetManagedGroup(DocumentTemplate DocumentTemplate, out DocumentTemplateDevicesManagedGroup ManagedGroup)
{
ADManagedGroup managedGroup;
string key = GetKey(DocumentTemplate);
if (ActiveDirectory.Context.ManagedGroups.TryGetValue(key, out managedGroup))
{
ManagedGroup = (DocumentTemplateDevicesManagedGroup)managedGroup;
return true;
}
else
{
ManagedGroup = null;
return false;
}
}
public static DocumentTemplateDevicesManagedGroup Initialize(DocumentTemplate Template)
{
var key = GetKey(Template);
if (!string.IsNullOrEmpty(Template.DevicesLinkedGroup))
{
var config = ADManagedGroup.ConfigurationFromJson(Template.DevicesLinkedGroup);
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
{
var group = new DocumentTemplateDevicesManagedGroup(
key,
config,
Template);
// Add to AD Context
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
return group;
}
}
// Remove from AD Context
ActiveDirectory.Context.ManagedGroups.Remove(key);
return null;
}
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
{
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
return Database.Devices
.Where(d => d.DeviceDomainId != null && d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.Select(d => d.DeviceDomainId)
.ToList()
.Where(ActiveDirectory.IsValidDomainAccountId)
.Select(id => id + "$");
case DocumentTemplate.DocumentTemplateScopes.Job:
return Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.Device.DeviceDomainId != null && j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.Select(j => j.Device.DeviceDomainId)
.Distinct()
.ToList()
.Where(ActiveDirectory.IsValidDomainAccountId)
.Select(id => id + "$");
case DocumentTemplate.DocumentTemplateScopes.User:
return Database.Users
.Where(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.SelectMany(u => u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue && dua.Device.DeviceDomainId != null), (u, dua) => dua.Device.DeviceDomainId)
.ToList()
.Where(ActiveDirectory.IsValidDomainAccountId)
.Select(id => id + "$");
default:
return Enumerable.Empty<string>();
}
}
#region Device Scope
private bool DeviceContainsAttachment(DiscoDataContext Database, string DeviceSerialNumber, out string DeviceAccountId)
{
var result = Database.Devices
.Where(d => d.SerialNumber == DeviceSerialNumber && d.DeviceDomainId != null)
.Select(d => new Tuple<string, bool>(d.DeviceDomainId, d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
.FirstOrDefault();
if (result == null)
{
DeviceAccountId = null;
return false;
}
else
{
if (ActiveDirectory.IsValidDomainAccountId(result.Item1))
{
DeviceAccountId = result.Item1 + "$";
return result.Item2;
}
else
{
DeviceAccountId = result.Item1 + "$";
return false;
}
}
}
private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (DeviceAttachment)e.Entity;
string deviceAccountId;
if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out deviceAccountId))
AddMember(attachment.DeviceSerialNumber, (database) => new string[] { deviceAccountId });
}
private void ProcessDeviceAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
{
var deviceSerialNumber = e.Item3;
RemoveMember(deviceSerialNumber, (database) =>
{
string deviceAccountId;
if (!DeviceContainsAttachment(database, deviceSerialNumber, out deviceAccountId) && deviceAccountId != null)
return new string[] { deviceAccountId };
else
return null;
});
}
#endregion
#region Job Scope
private bool JobsContainAttachment(DiscoDataContext Database, int JobId, out string DeviceAccountId, out string DeviceSerialNumber)
{
var result = Database.Jobs
.Where(j => j.Id == JobId && j.Device.DeviceDomainId != null)
.Select(j => new Tuple<string, string, bool>(
j.Device.DeviceDomainId,
j.Device.SerialNumber,
j.Device.Jobs.Where(dj => !dj.ClosedDate.HasValue).Any(dj => dj.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
).FirstOrDefault();
if (result == null)
{
DeviceAccountId = null;
DeviceSerialNumber = null;
return false;
}
else
{
if (ActiveDirectory.IsValidDomainAccountId(result.Item1))
{
DeviceAccountId = result.Item1 + "$";
DeviceSerialNumber = result.Item2;
return result.Item3;
}
else
{
DeviceAccountId = result.Item1 + "$";
DeviceSerialNumber = result.Item2;
return false;
}
}
}
private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (JobAttachment)e.Entity;
string deviceAccountId;
string deviceSerialNumber;
if (JobsContainAttachment(e.Database, attachment.JobId, out deviceAccountId, out deviceSerialNumber))
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
}
private void ProcessJobAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, int> e)
{
var jobId = e.Item4;
string deviceSerialNumber = e.Item1.Jobs.Where(j => j.Id == jobId && j.DeviceSerialNumber != null).Select(j => j.DeviceSerialNumber).FirstOrDefault();
if (deviceSerialNumber != null)
{
RemoveMember(deviceSerialNumber, (database) =>
{
string deviceAccountId;
if (!JobsContainAttachment(database, jobId, out deviceAccountId, out deviceSerialNumber) &&
deviceSerialNumber != null && deviceAccountId != null)
return new string[] { deviceAccountId };
else
return null;
});
}
}
#endregion
#region User Scope
private bool DeviceUserContainAttachment(DiscoDataContext Database, string UserId, out List<Tuple<string, string>> Devices)
{
var result = Database.Users
.Where(u => u.UserId == UserId)
.Select(u => new Tuple<bool, IEnumerable<Tuple<string, string>>>(
u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId),
u.DeviceUserAssignments
.Where(dua => !dua.UnassignedDate.HasValue && dua.Device.DeviceDomainId != null)
.Select(dua => new Tuple<string, string>(dua.Device.DeviceDomainId, dua.Device.SerialNumber)))
).FirstOrDefault();
if (result == null)
{
Devices = null;
return false;
}
else
{
Devices = result.Item2
.Where(d => ActiveDirectory.IsValidDomainAccountId(d.Item1))
.Select(d => Tuple.Create(d.Item1 + "$", d.Item2))
.ToList();
return result.Item1;
}
}
private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (UserAttachment)e.Entity;
List<Tuple<string, string>> devices;
if (DeviceUserContainAttachment(e.Database, attachment.UserId, out devices) && devices != null)
devices.ForEach(d => AddMember(d.Item2, (database) => new string[] { d.Item1 }));
}
private void ProcessUserAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
{
var userId = e.Item4;
RemoveMember(userId, (database) =>
{
List<Tuple<string, string>> devices;
if (!DeviceUserContainAttachment(database, userId, out devices) && devices != null)
return devices.Select(d => d.Item1);
else
return null;
});
}
#endregion
private void ProcessDeviceRenameRepositoryEvent(RepositoryMonitorEvent Event)
{
var device = (Device)Event.Entity;
var deviceSerialNumber = device.SerialNumber;
var deviceAccountId = device.DeviceDomainId;
var deviceAccountIdValid = ActiveDirectory.IsValidDomainAccountId(deviceAccountId);
var devicePreviousAccountId = Event.GetPreviousPropertyValue<string>("DeviceDomainId");
var devicePreviousAccountIdValid = ActiveDirectory.IsValidDomainAccountId(devicePreviousAccountId);
if (deviceAccountIdValid || devicePreviousAccountIdValid)
{
Event.ExecuteAfterCommit(e =>
{
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
if (DeviceContainsAttachment(e.Database, device.SerialNumber, out deviceAccountId))
{
if (deviceAccountIdValid)
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId });
if (devicePreviousAccountIdValid)
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
}
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
var jobsHaveTemplate = e.Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.DeviceSerialNumber == deviceSerialNumber)
.Any(j => j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
if (jobsHaveTemplate)
{
if (deviceAccountIdValid)
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId + "$" });
if (devicePreviousAccountIdValid)
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
}
break;
case DocumentTemplate.DocumentTemplateScopes.User:
var userHasTemplate = e.Database.Devices
.Where(d => d.SerialNumber == deviceSerialNumber)
.Select(d => d.AssignedUser)
.Any(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
if (userHasTemplate)
{
if (deviceAccountIdValid)
AddMember(device.SerialNumber, (database) => new string[] { deviceAccountId + "$" });
if (devicePreviousAccountIdValid)
RemoveMember(device.SerialNumber, (database) => new string[] { devicePreviousAccountId + "$" });
}
break;
}
});
}
}
private void ProcessJobCloseRepositoryEvent(RepositoryMonitorEvent e)
{
var job = (Job)e.Entity;
if (job.DeviceSerialNumber != null)
{
var jobId = job.Id;
var relevantJob = e.Database.Jobs
.Where(j => j.Id == jobId && j.JobAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
.Any();
if (relevantJob)
{
string deviceAccountId;
string deviceSerialNumber;
if (JobsContainAttachment(e.Database, jobId, out deviceAccountId, out deviceSerialNumber))
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
else
RemoveMember(deviceSerialNumber, (database) => new string[] { deviceAccountId });
}
}
}
private void ProcessDeviceAssignmentRepositoryEvent(RepositoryMonitorEvent Event)
{
var device = (Device)Event.Entity;
var deviceSerialNumber = device.SerialNumber;
var deviceAccountId = device.DeviceDomainId;
if (ActiveDirectory.IsValidDomainAccountId(deviceAccountId))
{
var deviceCurrentAssignedUserId = device.AssignedUserId;
var devicePreviousAssignedUserId = Event.GetPreviousPropertyValue<string>("AssignedUserId");
Event.ExecuteAfterCommit(e =>
{
bool previousUserHasTemplate = false;
bool currentUserHasTemplate = false;
if (devicePreviousAssignedUserId != null)
previousUserHasTemplate = e.Database.Users
.Where(u => u.UserId == devicePreviousAssignedUserId && u.UserAttachments.Any(ua => ua.DocumentTemplateId == this.DocumentTemplateId))
.Any();
if (deviceCurrentAssignedUserId != null)
currentUserHasTemplate = e.Database.Users
.Where(u => u.UserId == deviceCurrentAssignedUserId && u.UserAttachments.Any(ua => ua.DocumentTemplateId == this.DocumentTemplateId))
.Any();
if (!previousUserHasTemplate && currentUserHasTemplate)
AddMember(deviceSerialNumber, (database) => new string[] { deviceAccountId + "$" });
else if (previousUserHasTemplate && !currentUserHasTemplate)
RemoveMember(deviceSerialNumber, (database) => new string[] { deviceAccountId + "$" });
});
}
}
public override void Dispose()
{
if (repositoryAddSubscription != null)
repositoryAddSubscription.Dispose();
if (repositoryRemoveSubscription != null)
repositoryRemoveSubscription.Dispose();
if (deviceRenameRepositorySubscription != null)
deviceRenameRepositorySubscription.Dispose();
if (jobCloseRepositorySubscription != null)
jobCloseRepositorySubscription.Dispose();
if (deviceAssignmentRepositorySubscription != null)
deviceAssignmentRepositorySubscription.Dispose();
}
}
}
@@ -0,0 +1,110 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using System;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
{
public static class DocumentTemplateManagedGroups
{
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceAttachmentAddRepositoryEvents;
internal static Lazy<IObservable<RepositoryMonitorEvent>> JobAttachmentAddRepositoryEvents;
internal static Lazy<IObservable<RepositoryMonitorEvent>> UserAttachmentAddRepositoryEvents;
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>> DeviceAttachmentRemoveEvents;
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, int>>> JobAttachmentRemoveEvents;
internal static Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>> UserAttachmentRemoveEvents;
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceRenameRepositoryEvents;
internal static Lazy<IObservable<RepositoryMonitorEvent>> JobCloseRepositoryEvents;
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceAssignmentRepositoryEvents;
static DocumentTemplateManagedGroups()
{
DeviceAttachmentAddRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(DeviceAttachment) &&
((DeviceAttachment)e.Entity).DocumentTemplateId != null &&
e.EventType == RepositoryMonitorEventType.Added
));
JobAttachmentAddRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(JobAttachment) &&
((JobAttachment)e.Entity).DocumentTemplateId != null &&
e.EventType == RepositoryMonitorEventType.Added
));
UserAttachmentAddRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(UserAttachment) &&
((UserAttachment)e.Entity).DocumentTemplateId != null &&
e.EventType == RepositoryMonitorEventType.Added
));
DeviceAttachmentRemoveEvents =
new Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>>(() => new Subject<Tuple<DiscoDataContext, int, string, string>>());
JobAttachmentRemoveEvents =
new Lazy<Subject<Tuple<DiscoDataContext, int, string, int>>>(() => new Subject<Tuple<DiscoDataContext, int, string, int>>());
UserAttachmentRemoveEvents =
new Lazy<Subject<Tuple<DiscoDataContext, int, string, string>>>(() => new Subject<Tuple<DiscoDataContext, int, string, string>>());
DeviceRenameRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamBeforeCommit.Where(e =>
e.EntityType == typeof(Device) &&
e.EventType == RepositoryMonitorEventType.Modified &&
e.ModifiedProperties.Contains("DeviceDomainId")
));
JobCloseRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(Job) &&
(((Job)e.Entity).DeviceSerialNumber != null || ((Job)e.Entity).UserId != null) &&
e.EventType == RepositoryMonitorEventType.Modified &&
e.ModifiedProperties.Contains("ClosedDate")
));
DeviceAssignmentRepositoryEvents =
new Lazy<IObservable<RepositoryMonitorEvent>>(() =>
RepositoryMonitor.StreamBeforeCommit.Where(e =>
e.EntityType == typeof(Device) &&
e.EventType == RepositoryMonitorEventType.Modified &&
e.ModifiedProperties.Contains("AssignedUserId")
));
}
public static void Initialize(DiscoDataContext Database)
{
Database.DocumentTemplates
.Where(dp => dp.DevicesLinkedGroup != null || dp.UsersLinkedGroup != null)
.ToList()
.ForEach(dp =>
{
DocumentTemplateDevicesManagedGroup.Initialize(dp);
DocumentTemplateUsersManagedGroup.Initialize(dp);
});
}
public static void TriggerDeviceAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string DeviceSerialNumber)
{
if (DocumentTemplateId != null)
DeviceAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, DeviceSerialNumber));
}
public static void TriggerJobAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, int JobId)
{
if (DocumentTemplateId != null)
JobAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, JobId));
}
public static void TriggerUserAttachmentDeleted(DiscoDataContext Database, int AttachmentId, string DocumentTemplateId, string UserId)
{
if (DocumentTemplateId != null)
UserAttachmentRemoveEvents.Value.OnNext(Tuple.Create(Database, AttachmentId, DocumentTemplateId, UserId));
}
}
}
@@ -0,0 +1,365 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
using Disco.Models.Services.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
namespace Disco.BI.DocumentTemplateBI.ManagedGroups
{
public class DocumentTemplateUsersManagedGroup : ADManagedGroup
{
private const string KeyFormat = "DocumentTemplate_{0}_Users";
private const string UserDescriptionFormat = "Users with a {0} attachment will be added to this Active Directory group.";
private const string DescriptionFormat = "{0}s with a {1} attachment will have any associated users added to this Active Directory group.";
private const string CategoryDescriptionFormat = "Related Users Linked Group";
private const string GroupDescriptionFormat = "{0} [Document Template Users]";
private IDisposable repositoryAddSubscription;
private IDisposable repositoryRemoveSubscription;
private IDisposable jobCloseRepositorySubscription;
private IDisposable deviceAssignmentRepositorySubscription;
private string DocumentTemplateId;
private string DocumentTemplateDescription;
private string DocumentTemplateScope;
public override string Description { get { return GetDescription(DocumentTemplateScope, DocumentTemplateDescription); } }
public override string CategoryDescription { get { return CategoryDescriptionFormat; } }
public override string GroupDescription { get { return string.Format(GroupDescriptionFormat, DocumentTemplateDescription); } }
public override bool IncludeFilterBeginDate { get { return true; } }
private DocumentTemplateUsersManagedGroup(string Key, ADManagedGroupConfiguration Configuration, DocumentTemplate DocumentTemplate)
: base(Key, Configuration)
{
this.DocumentTemplateId = DocumentTemplate.Id;
this.DocumentTemplateDescription = DocumentTemplate.Description;
this.DocumentTemplateScope = DocumentTemplate.Scope;
}
public override void Initialize()
{
// Subscribe to changes
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
// Observe Device Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.DeviceAttachmentAddRepositoryEvents.Value
.Where(e => ((DeviceAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessDeviceAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.DeviceAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessDeviceAttachmentRemoveEvent);
// Observe Device Assignments
deviceAssignmentRepositorySubscription = DocumentTemplateManagedGroups.DeviceAssignmentRepositoryEvents.Value
.Subscribe(ProcessDeviceAssignmentRepositoryEvent);
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
// Observe Job Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
.Where(e => ((JobAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessJobAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.JobAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessJobAttachmentRemoveEvent);
// Observe Job Close/Reopen
jobCloseRepositorySubscription = DocumentTemplateManagedGroups.JobCloseRepositoryEvents.Value
.Subscribe(ProcessJobCloseRepositoryEvent);
break;
case DocumentTemplate.DocumentTemplateScopes.User:
// Observe User Attachments
repositoryAddSubscription = DocumentTemplateManagedGroups.UserAttachmentAddRepositoryEvents.Value
.Where(e => ((UserAttachment)e.Entity).DocumentTemplateId == DocumentTemplateId)
.Subscribe(ProcessUserAttachmentAddEvent);
repositoryRemoveSubscription = DocumentTemplateManagedGroups.UserAttachmentRemoveEvents.Value
.Where(e => e.Item3 == DocumentTemplateId)
.Subscribe(ProcessUserAttachmentRemoveEvent);
break;
}
}
public static string GetKey(DocumentTemplate DocumentTemplate)
{
return string.Format(KeyFormat, DocumentTemplate.Id);
}
private static string GetDescription(string DocumentTemplateScope, string DocumentTemplateDescription)
{
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
case DocumentTemplate.DocumentTemplateScopes.Job:
return string.Format(DescriptionFormat, DocumentTemplateScope, DocumentTemplateDescription);
case DocumentTemplate.DocumentTemplateScopes.User:
return string.Format(UserDescriptionFormat, DocumentTemplateDescription);
default:
throw new ArgumentException("Unknown Document Template Scope", "Scope");
}
}
public static string GetDescription(DocumentTemplate DocumentTemplate)
{
return GetDescription(DocumentTemplate.Scope, DocumentTemplate.Description);
}
public static string GetCategoryDescription(DocumentTemplate DocumentTemplate)
{
return CategoryDescriptionFormat;
}
public static bool TryGetManagedGroup(DocumentTemplate DocumentTemplate, out DocumentTemplateUsersManagedGroup ManagedGroup)
{
ADManagedGroup managedGroup;
string key = GetKey(DocumentTemplate);
if (ActiveDirectory.Context.ManagedGroups.TryGetValue(key, out managedGroup))
{
ManagedGroup = (DocumentTemplateUsersManagedGroup)managedGroup;
return true;
}
else
{
ManagedGroup = null;
return false;
}
}
public static DocumentTemplateUsersManagedGroup Initialize(DocumentTemplate Template)
{
var key = GetKey(Template);
if (!string.IsNullOrEmpty(Template.UsersLinkedGroup))
{
var config = ADManagedGroup.ConfigurationFromJson(Template.UsersLinkedGroup);
if (config != null && !string.IsNullOrWhiteSpace(config.GroupId))
{
var group = new DocumentTemplateUsersManagedGroup(
key,
config,
Template);
// Add to AD Context
ActiveDirectory.Context.ManagedGroups.AddOrUpdate(group);
return group;
}
}
// Remove from AD Context
ActiveDirectory.Context.ManagedGroups.Remove(key);
return null;
}
public override IEnumerable<string> DetermineMembers(DiscoDataContext Database)
{
switch (DocumentTemplateScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
return Database.Devices
.Where(d => d.AssignedUserId != null && d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.Select(d => d.AssignedUserId);
case DocumentTemplate.DocumentTemplateScopes.Job:
return Database.Jobs
.Where(j => !j.ClosedDate.HasValue && j.UserId != null && j.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.Select(j => j.UserId)
.Distinct();
case DocumentTemplate.DocumentTemplateScopes.User:
return Database.Users
.Where(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId))
.Select(u => u.UserId);
default:
return Enumerable.Empty<string>();
}
}
#region Device Scope
private bool DeviceContainsAttachment(DiscoDataContext Database, string DeviceSerialNumber, out string UserId)
{
var result = Database.Devices
.Where(d => d.SerialNumber == DeviceSerialNumber && d.AssignedUser != null)
.Select(d => new Tuple<string, bool>(d.AssignedUserId, d.DeviceAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
.FirstOrDefault();
if (result == null)
{
UserId = null;
return false;
}
else
{
UserId = result.Item1;
return result.Item2;
}
}
private void ProcessDeviceAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (DeviceAttachment)e.Entity;
string userId;
if (DeviceContainsAttachment(e.Database, attachment.DeviceSerialNumber, out userId) && userId != null)
AddMember(userId, (database) => new string[] { userId });
}
private void ProcessDeviceAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
{
var deviceSerialNumber = e.Item4;
string userId = e.Item1.Devices.Where(d => d.SerialNumber == deviceSerialNumber && d.AssignedUserId != null).Select(j => j.AssignedUserId).FirstOrDefault();
if (userId != null)
{
RemoveMember(userId, (database) =>
{
if (DeviceContainsAttachment(database, deviceSerialNumber, out userId) && userId != null)
return new string[] { userId };
else
return null;
});
}
}
#endregion
#region Job Scope
private bool JobsContainAttachment(DiscoDataContext Database, int JobId, out string UserId)
{
var result = Database.Jobs
.Where(j => j.Id == JobId && j.UserId != null)
.Select(j => new Tuple<string, bool>(
j.UserId,
j.User.Jobs.Where(uj => !uj.ClosedDate.HasValue).Any(uj => uj.JobAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId)))
).FirstOrDefault();
if (result == null)
{
UserId = null;
return false;
}
else
{
UserId = result.Item1;
return result.Item2;
}
}
private void ProcessJobAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (JobAttachment)e.Entity;
string userId;
if (JobsContainAttachment(e.Database, attachment.JobId, out userId) && userId != null)
AddMember(userId, (database) => new string[] { userId });
}
private void ProcessJobAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, int> e)
{
var jobId = e.Item4;
string userId = e.Item1.Jobs.Where(j => j.Id == jobId && j.UserId != null).Select(j => j.UserId).FirstOrDefault();
if (userId != null)
{
RemoveMember(userId, (database) =>
{
if (JobsContainAttachment(database, jobId, out userId) && userId != null)
return new string[] { userId };
else
return null;
});
}
}
#endregion
#region User Scope
private bool UserContainAttachment(DiscoDataContext Database, string UserId)
{
var result = Database.Users
.Where(u => u.UserId == UserId)
.Any(u => u.UserAttachments.Any(a => a.DocumentTemplateId == this.DocumentTemplateId));
return result;
}
private void ProcessUserAttachmentAddEvent(RepositoryMonitorEvent e)
{
var attachment = (UserAttachment)e.Entity;
var userId = attachment.UserId;
if (UserContainAttachment(e.Database, userId) && userId != null)
AddMember(userId, (database) => new string[] { userId });
}
private void ProcessUserAttachmentRemoveEvent(Tuple<DiscoDataContext, int, string, string> e)
{
var userId = e.Item4;
RemoveMember(userId, (database) =>
{
if (!UserContainAttachment(database, userId))
return new string[] { userId };
else
return null;
});
}
#endregion
private void ProcessJobCloseRepositoryEvent(RepositoryMonitorEvent e)
{
var job = (Job)e.Entity;
if (job.UserId != null)
{
var jobId = job.Id;
var relevantJob = e.Database.Jobs
.Where(j => j.Id == jobId && j.JobAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
.Any();
if (relevantJob)
{
string userId;
if (JobsContainAttachment(e.Database, jobId, out userId))
AddMember(userId, (database) => new string[] { userId });
else
RemoveMember(userId, (database) => new string[] { userId });
}
}
}
private void ProcessDeviceAssignmentRepositoryEvent(RepositoryMonitorEvent Event)
{
var device = (Device)Event.Entity;
var deviceSerialNumber = device.SerialNumber;
var relevantDevice = Event.Database.Devices
.Where(d => d.SerialNumber == deviceSerialNumber && d.DeviceAttachments.Any(ja => ja.DocumentTemplateId == this.DocumentTemplateId))
.Any();
if (relevantDevice)
{
var deviceCurrentAssignedUserId = device.AssignedUserId;
var devicePreviousAssignedUserId = Event.GetPreviousPropertyValue<string>("AssignedUserId");
Event.ExecuteAfterCommit(e =>
{
if (devicePreviousAssignedUserId != null)
RemoveMember(devicePreviousAssignedUserId, (database) => new string[] { devicePreviousAssignedUserId });
if (deviceCurrentAssignedUserId != null)
AddMember(deviceCurrentAssignedUserId, (database) => new string[] { deviceCurrentAssignedUserId });
});
}
}
public override void Dispose()
{
if (repositoryAddSubscription != null)
repositoryAddSubscription.Dispose();
if (repositoryRemoveSubscription != null)
repositoryRemoveSubscription.Dispose();
if (jobCloseRepositorySubscription != null)
jobCloseRepositorySubscription.Dispose();
if (deviceAssignmentRepositorySubscription != null)
deviceAssignmentRepositorySubscription.Dispose();
}
}
}
+2 -2
View File
@@ -167,14 +167,14 @@ namespace Disco.BI.Expressions
return e;
}
public static IDictionary StandardVariables(DocumentTemplate AttachmentType, DiscoDataContext DataContext, User User, System.DateTime TimeStamp, DocumentState DocumentState)
public static IDictionary StandardVariables(DocumentTemplate AttachmentType, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState DocumentState)
{
return new Hashtable
{
{
"DataContext",
DataContext
Database
},
{
@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Services.Tasks;
using Disco.BI.Extensions;
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
using Disco.BI.Extensions;
using System.Diagnostics;
using System;
using System.Linq;
namespace Disco.BI.Expressions
{
@@ -16,10 +13,11 @@ namespace Disco.BI.Expressions
public override string TaskName { get { return "Expression Cache - Preload Task"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Run in Background 1 Second after Scheduled (on App Startup)
// Run in Background 5 Second after Scheduled (on App Startup)
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now).AddSeconds(5));
this.ScheduleTask(triggerBuilder);
@@ -28,16 +26,14 @@ namespace Disco.BI.Expressions
protected override void ExecuteTask()
{
// Cache Document Template Filter Expressions
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
foreach (var documentTemplate in dbContext.DocumentTemplates.Where(dt => dt.FilterExpression != null && dt.FilterExpression != string.Empty))
foreach (var documentTemplate in database.DocumentTemplates.Where(dt => dt.FilterExpression != null && dt.FilterExpression != string.Empty))
{
if (!string.IsNullOrWhiteSpace(documentTemplate.FilterExpression))
documentTemplate.FilterExpressionFromCache();
}
}
}
}
}
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.BI.Extensions;
using Disco.Models.Repository;
using Disco.BI.Extensions;
using Disco.BI.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
using System;
using System.Linq;
namespace Disco.BI.Expressions.Extensions
{
@@ -14,7 +12,7 @@ namespace Disco.BI.Expressions.Extensions
{
var adMachineAccount = Device.ActiveDirectoryAccount(PropertyName);
if (adMachineAccount != null)
return adMachineAccount.GetPropertyValue(PropertyName, Index);
return adMachineAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
else
return null;
}
+15 -15
View File
@@ -26,66 +26,66 @@ namespace Disco.BI.Expressions.Extensions
string AbsoluteFilePath = System.IO.Path.Combine(DataStoreLocation, RelativeFilePath);
return new FileImageExpressionResult(AbsoluteFilePath);
}
public static FileImageExpressionResult JobAttachmentFirstImage(Job Job, DiscoDataContext dbContext)
public static FileImageExpressionResult JobAttachmentFirstImage(Job Job, DiscoDataContext Database)
{
var attachment = Job.JobAttachments.FirstOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase));
var attachment = Job.JobAttachments.FirstOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
if (attachment != null)
{
var filename = attachment.RepositoryFilename(dbContext);
var filename = attachment.RepositoryFilename(Database);
return new FileImageExpressionResult(filename);
}
else
return null;
}
public static FileImageExpressionResult JobAttachmentLastImage(Job Job, DiscoDataContext dbContext)
public static FileImageExpressionResult JobAttachmentLastImage(Job Job, DiscoDataContext Database)
{
var attachment = Job.JobAttachments.LastOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase));
var attachment = Job.JobAttachments.LastOrDefault(ja => ja.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase));
if (attachment != null)
{
var filename = attachment.RepositoryFilename(dbContext);
var filename = attachment.RepositoryFilename(Database);
return new FileImageExpressionResult(filename);
}
else
return null;
}
public static FileImageExpressionResult JobAttachmentImage(JobAttachment JobAttachment, DiscoDataContext dbContext)
public static FileImageExpressionResult JobAttachmentImage(JobAttachment JobAttachment, DiscoDataContext Database)
{
if (JobAttachment == null)
throw new ArgumentNullException("JobAttachment");
if (!JobAttachment.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase))
if (!JobAttachment.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
throw new ArgumentException("Invalid Image MimeType for Attachment");
var filename = JobAttachment.RepositoryFilename(dbContext);
var filename = JobAttachment.RepositoryFilename(Database);
return new FileImageExpressionResult(filename);
}
public static FileMontageImageExpressionResult JobAttachmentImageMontage(Job Job, DiscoDataContext dbContext)
public static FileMontageImageExpressionResult JobAttachmentImageMontage(Job Job, DiscoDataContext Database)
{
if (Job == null)
throw new ArgumentNullException("Job");
if (Job.JobAttachments == null)
throw new ArgumentException("Job.JobAttachments is null", "Job");
var attachments = Job.JobAttachments.Where(a => a.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase)).ToList();
var attachments = Job.JobAttachments.Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
if (attachments.Count > 0)
{
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(dbContext)).ToList();
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(Database)).ToList();
return new FileMontageImageExpressionResult(attachmentFilepaths);
}
else
return null;
}
public static FileMontageImageExpressionResult JobAttachmentsImageMontage(ArrayList JobAttachments, DiscoDataContext dbContext)
public static FileMontageImageExpressionResult JobAttachmentsImageMontage(ArrayList JobAttachments, DiscoDataContext Database)
{
if (JobAttachments == null)
throw new ArgumentNullException("JobAttachments");
var attachments = JobAttachments.Cast<JobAttachment>().Where(a => a.MimeType.StartsWith("image/", StringComparison.InvariantCultureIgnoreCase)).ToList();
var attachments = JobAttachments.Cast<JobAttachment>().Where(a => a.MimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)).ToList();
if (attachments.Count > 0)
{
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(dbContext)).ToList();
var attachmentFilepaths = attachments.Select(a => a.RepositoryFilename(Database)).ToList();
return new FileMontageImageExpressionResult(attachmentFilepaths);
}
+30 -7
View File
@@ -1,20 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.BI.Extensions;
using Disco.Models.Repository;
using Disco.BI.Extensions;
using Disco.BI.Interop.ActiveDirectory;
using Disco.Services.Users;
using System;
using System.Linq;
namespace Disco.BI.Expressions.Extensions
{
public static class UserExt
{
#region Active Directory Extensions
public static object GetActiveDirectoryObjectValue(User User, string PropertyName, int Index = 0)
{
var adUserAccount = User.ActiveDirectoryAccount(PropertyName);
if (adUserAccount != null)
return adUserAccount.GetPropertyValue(PropertyName, Index);
return adUserAccount.GetPropertyValues<object>(PropertyName).Skip(Index).FirstOrDefault();
else
return null;
}
@@ -47,5 +46,29 @@ namespace Disco.BI.Expressions.Extensions
return intValue;
}
}
#endregion
#region Authorization Testing Extensions
public static bool HasAuthorization(User User, string Claim)
{
var authorization = UserService.GetAuthorization(User.UserId);
return authorization.Has(Claim);
}
public static bool HasAuthorizationAll(User User, params string[] Claims)
{
var authorization = UserService.GetAuthorization(User.UserId);
return authorization.HasAll(Claims);
}
public static bool HasAuthorizationAny(User User, params string[] Claims)
{
var authorization = UserService.GetAuthorization(User.UserId);
return authorization.HasAny(Claims);
}
#endregion
}
}
@@ -4,6 +4,9 @@ using System.Linq;
using System.Text;
using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
using Disco.BI.DocumentTemplateBI.ManagedGroups;
namespace Disco.BI.Extensions
{
@@ -13,39 +16,78 @@ namespace Disco.BI.Extensions
#region Delete
public static bool CanDelete(this DeviceAttachment da)
{
return true; // Placeholder - Currently Can Always Delete;
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveAnyAttachments))
return true;
if (UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveOwnAttachments)
&& da.TechUserId == UserService.CurrentUserId)
return true;
return false;
}
public static void OnDelete(this DeviceAttachment da, DiscoDataContext dbContext)
public static void OnDelete(this DeviceAttachment da, DiscoDataContext Database)
{
if (!da.CanDelete())
throw new InvalidOperationException("Deletion of Attachment is Denied");
da.RepositoryDelete(dbContext);
dbContext.DeviceAttachments.Remove(da);
var attachmentId = da.Id;
var documentTemplateId = da.DocumentTemplateId;
var deviceSerialNumber = da.DeviceSerialNumber;
da.RepositoryDelete(Database);
Database.DeviceAttachments.Remove(da);
DocumentTemplateManagedGroups.TriggerDeviceAttachmentDeleted(Database, attachmentId, documentTemplateId, deviceSerialNumber);
}
public static bool CanDelete(this JobAttachment ja)
{
return true; // Placeholder - Currently Can Always Delete;
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyAttachments))
return true;
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnAttachments)
&& ja.TechUserId == UserService.CurrentUserId)
return true;
return false;
}
public static void OnDelete(this JobAttachment ja, DiscoDataContext dbContext)
public static void OnDelete(this JobAttachment ja, DiscoDataContext Database)
{
if (!ja.CanDelete())
throw new InvalidOperationException("Deletion of Attachment is Denied");
ja.RepositoryDelete(dbContext);
dbContext.JobAttachments.Remove(ja);
var attachmentId = ja.Id;
var documentTemplateId = ja.DocumentTemplateId;
var jobId = ja.JobId;
ja.RepositoryDelete(Database);
Database.JobAttachments.Remove(ja);
DocumentTemplateManagedGroups.TriggerJobAttachmentDeleted(Database, attachmentId, documentTemplateId, jobId);
}
public static bool CanDelete(this UserAttachment ua)
{
return true; // Placeholder - Currently Can Always Delete;
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveAnyAttachments))
return true;
if (UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveOwnAttachments)
&& ua.TechUserId == UserService.CurrentUserId)
return true;
return false;
}
public static void OnDelete(this UserAttachment ua, DiscoDataContext dbContext)
public static void OnDelete(this UserAttachment ua, DiscoDataContext Database)
{
if (!ua.CanDelete())
throw new InvalidOperationException("Deletion of Attachment is Denied");
ua.RepositoryDelete(dbContext);
dbContext.UserAttachments.Remove(ua);
var attachmentId = ua.Id;
var documentTemplateId = ua.DocumentTemplateId;
var userId = ua.UserId;
ua.RepositoryDelete(Database);
Database.UserAttachments.Remove(ua);
DocumentTemplateManagedGroups.TriggerUserAttachmentDeleted(Database, attachmentId, documentTemplateId, userId);
}
#endregion
+54 -53
View File
@@ -6,23 +6,24 @@ using Disco.Models.Repository;
using Disco.Data.Repository;
using System.IO;
using Disco.BI.DocumentTemplateBI;
using Disco.Services.Users;
namespace Disco.BI.Extensions
{
public static class AttachmentExtensions
{
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext dbContext, System.IO.Stream PdfContent, byte[] PdfThumbnail)
public static bool ImportPdfAttachment(this DocumentUniqueIdentifier UniqueIdentifier, DiscoDataContext Database, System.IO.Stream PdfContent, byte[] PdfThumbnail)
{
UniqueIdentifier.LoadComponents(dbContext);
UniqueIdentifier.LoadComponents(Database);
DocumentTemplate documentTemplate = UniqueIdentifier.DocumentTemplate;
string filename;
string comments;
if (documentTemplate == null)
{
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId, UniqueIdentifier.TimeStamp);
filename = string.Format("{0}_{1:yyyyMMdd-HHmmss}.pdf", UniqueIdentifier.DataId.Replace('\\', '_'), UniqueIdentifier.TimeStamp);
comments = string.Format("Uploaded: {0:s}", UniqueIdentifier.TimeStamp);
}
else
@@ -31,25 +32,25 @@ namespace Disco.BI.Extensions
comments = string.Format("Generated: {0:s}", UniqueIdentifier.TimeStamp);
}
User creatorUser = UserBI.UserCache.GetUser(UniqueIdentifier.CreatorId, dbContext);
User creatorUser = UserService.GetUser(UniqueIdentifier.CreatorId, Database);
if (creatorUser == null)
{
// No Creator User (or Username invalid)
creatorUser = UserBI.UserCache.CurrentUser;
creatorUser = UserService.CurrentUser;
}
switch (UniqueIdentifier.DataScope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
Device d = (Device)UniqueIdentifier.Data;
d.CreateAttachment(dbContext, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
d.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
case DocumentTemplate.DocumentTemplateScopes.Job:
Job j = (Job)UniqueIdentifier.Data;
j.CreateAttachment(dbContext, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
j.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
case DocumentTemplate.DocumentTemplateScopes.User:
User u = (User)UniqueIdentifier.Data;
u.CreateAttachment(dbContext, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
u.CreateAttachment(Database, creatorUser, filename, DocumentTemplate.PdfMimeType, comments, PdfContent, documentTemplate, PdfThumbnail);
return true;
default:
return false;
@@ -57,47 +58,47 @@ namespace Disco.BI.Extensions
}
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext dbContext)
public static string RepositoryFilename(this DeviceAttachment da, DiscoDataContext Database)
{
return Path.Combine(DataStore.CreateLocation(dbContext, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_file", da.DeviceSerialNumber, da.Id));
return Path.Combine(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_file", da.DeviceSerialNumber, da.Id));
}
public static string RepositoryFilename(this JobAttachment ja, DiscoDataContext dbContext)
public static string RepositoryFilename(this JobAttachment ja, DiscoDataContext Database)
{
return Path.Combine(DataStore.CreateLocation(dbContext, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_file", ja.JobId, ja.Id));
return Path.Combine(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_file", ja.JobId, ja.Id));
}
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext dbContext)
public static string RepositoryFilename(this UserAttachment ua, DiscoDataContext Database)
{
return Path.Combine(DataStore.CreateLocation(dbContext, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId, ua.Id));
return Path.Combine(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_file", ua.UserId.Replace('\\', '_'), ua.Id));
}
private static string RepositoryThumbnailFilenameInternal(string DirectoryPath, string Filename)
{
return Path.Combine(DirectoryPath, Filename);
}
public static string RepositoryThumbnailFilename(this DeviceAttachment da, DiscoDataContext dbContext)
public static string RepositoryThumbnailFilename(this DeviceAttachment da, DiscoDataContext Database)
{
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(dbContext, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_thumb.jpg", da.DeviceSerialNumber, da.Id));
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "DeviceAttachments", da.Timestamp), string.Format("{0}_{1}_thumb.jpg", da.DeviceSerialNumber, da.Id));
}
public static string RepositoryThumbnailFilename(this JobAttachment ja, DiscoDataContext dbContext)
public static string RepositoryThumbnailFilename(this JobAttachment ja, DiscoDataContext Database)
{
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(dbContext, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_thumb.jpg", ja.JobId, ja.Id));
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "JobAttachments", ja.Timestamp), string.Format("{0}_{1}_thumb.jpg", ja.JobId, ja.Id));
}
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext dbContext)
public static string RepositoryThumbnailFilename(this UserAttachment ua, DiscoDataContext Database)
{
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(dbContext, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId, ua.Id));
return RepositoryThumbnailFilenameInternal(DataStore.CreateLocation(Database, "UserAttachments", ua.Timestamp), string.Format("{0}_{1}_thumb.jpg", ua.UserId.Replace('\\', '_'), ua.Id));
}
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext dbContext)
public static void RepositoryDelete(this DeviceAttachment da, DiscoDataContext Database)
{
RepositoryDelete(da.RepositoryFilename(dbContext), da.RepositoryThumbnailFilename(dbContext));
RepositoryDelete(da.RepositoryFilename(Database), da.RepositoryThumbnailFilename(Database));
}
public static void RepositoryDelete(this JobAttachment ja, DiscoDataContext dbContext)
public static void RepositoryDelete(this JobAttachment ja, DiscoDataContext Database)
{
RepositoryDelete(ja.RepositoryFilename(dbContext), ja.RepositoryThumbnailFilename(dbContext));
RepositoryDelete(ja.RepositoryFilename(Database), ja.RepositoryThumbnailFilename(Database));
}
public static void RepositoryDelete(this UserAttachment ua, DiscoDataContext dbContext)
public static void RepositoryDelete(this UserAttachment ua, DiscoDataContext Database)
{
RepositoryDelete(ua.RepositoryFilename(dbContext), ua.RepositoryThumbnailFilename(dbContext));
RepositoryDelete(ua.RepositoryFilename(Database), ua.RepositoryThumbnailFilename(Database));
}
private static void RepositoryDelete(params string[] filePaths)
{
@@ -108,39 +109,39 @@ namespace Disco.BI.Extensions
}
}
public static string SaveAttachment(this DeviceAttachment da, DiscoDataContext dbContext, Stream FileContent)
public static string SaveAttachment(this DeviceAttachment da, DiscoDataContext Database, Stream FileContent)
{
string filePath = da.RepositoryFilename(dbContext);
string filePath = da.RepositoryFilename(Database);
SaveAttachment(filePath, FileContent);
return filePath;
}
public static string SaveAttachment(this JobAttachment ja, DiscoDataContext dbContext, Stream FileContent)
public static string SaveAttachment(this JobAttachment ja, DiscoDataContext Database, Stream FileContent)
{
string filePath = ja.RepositoryFilename(dbContext);
string filePath = ja.RepositoryFilename(Database);
SaveAttachment(filePath, FileContent);
return filePath;
}
public static string SaveAttachment(this UserAttachment ua, DiscoDataContext dbContext, Stream FileContent)
public static string SaveAttachment(this UserAttachment ua, DiscoDataContext Database, Stream FileContent)
{
string filePath = ua.RepositoryFilename(dbContext);
string filePath = ua.RepositoryFilename(Database);
SaveAttachment(filePath, FileContent);
return filePath;
}
public static string SaveThumbnailAttachment(this DeviceAttachment da, DiscoDataContext dbContext, byte[] FileContent)
public static string SaveThumbnailAttachment(this DeviceAttachment da, DiscoDataContext Database, byte[] FileContent)
{
string filePath = da.RepositoryThumbnailFilename(dbContext);
string filePath = da.RepositoryThumbnailFilename(Database);
File.WriteAllBytes(filePath, FileContent);
return filePath;
}
public static string SaveThumbnailAttachment(this JobAttachment ja, DiscoDataContext dbContext, byte[] FileContent)
public static string SaveThumbnailAttachment(this JobAttachment ja, DiscoDataContext Database, byte[] FileContent)
{
string filePath = ja.RepositoryThumbnailFilename(dbContext);
string filePath = ja.RepositoryThumbnailFilename(Database);
File.WriteAllBytes(filePath, FileContent);
return filePath;
}
public static string SaveThumbnailAttachment(this UserAttachment ua, DiscoDataContext dbContext, byte[] FileContent)
public static string SaveThumbnailAttachment(this UserAttachment ua, DiscoDataContext Database, byte[] FileContent)
{
string filePath = ua.RepositoryThumbnailFilename(dbContext);
string filePath = ua.RepositoryThumbnailFilename(Database);
File.WriteAllBytes(filePath, FileContent);
return filePath;
}
@@ -154,39 +155,39 @@ namespace Disco.BI.Extensions
}
}
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext dbContext)
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database)
{
string filePath = da.RepositoryThumbnailFilename(dbContext);
AttachmentBI.Utilities.GenerateThumbnail(da.RepositoryFilename(dbContext), da.MimeType, filePath);
string filePath = da.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(da.RepositoryFilename(Database), da.MimeType, filePath);
return filePath;
}
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext dbContext)
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database)
{
string filePath = ja.RepositoryThumbnailFilename(dbContext);
AttachmentBI.Utilities.GenerateThumbnail(ja.RepositoryFilename(dbContext), ja.MimeType, filePath);
string filePath = ja.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(ja.RepositoryFilename(Database), ja.MimeType, filePath);
return filePath;
}
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext dbContext)
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database)
{
string filePath = ua.RepositoryThumbnailFilename(dbContext);
AttachmentBI.Utilities.GenerateThumbnail(ua.RepositoryFilename(dbContext), ua.MimeType, filePath);
string filePath = ua.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(ua.RepositoryFilename(Database), ua.MimeType, filePath);
return filePath;
}
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext dbContext, Stream SourceFile)
public static string GenerateThumbnail(this DeviceAttachment da, DiscoDataContext Database, Stream SourceFile)
{
string filePath = da.RepositoryThumbnailFilename(dbContext);
string filePath = da.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, da.MimeType, filePath);
return filePath;
}
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext dbContext, Stream SourceFile)
public static string GenerateThumbnail(this JobAttachment ja, DiscoDataContext Database, Stream SourceFile)
{
string filePath = ja.RepositoryThumbnailFilename(dbContext);
string filePath = ja.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ja.MimeType, filePath);
return filePath;
}
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext dbContext, Stream SourceFile)
public static string GenerateThumbnail(this UserAttachment ua, DiscoDataContext Database, Stream SourceFile)
{
string filePath = ua.RepositoryThumbnailFilename(dbContext);
string filePath = ua.RepositoryThumbnailFilename(Database);
AttachmentBI.Utilities.GenerateThumbnail(SourceFile, ua.MimeType, filePath);
return filePath;
}
@@ -0,0 +1,28 @@
using Disco.Data.Repository;
using Disco.Models.Services.Authorization;
using Disco.Models.Repository;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Extensions
{
public static class AuthorizationRoleExtensions
{
public static void Delete(this IRoleToken roleToken, DiscoDataContext Database)
{
var role = Database.AuthorizationRoles.Find(roleToken.Role.Id);
UserService.DeleteAuthorizationRole(Database, roleToken.Role);
}
public static void Delete(this AuthorizationRole role, DiscoDataContext Database)
{
UserService.DeleteAuthorizationRole(Database, role);
}
}
}
@@ -6,6 +6,8 @@ using Disco.Models.ClientServices;
using System.Web;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
@@ -20,10 +22,10 @@ namespace Disco.BI.Extensions
if (HttpContext.Current.Request.IsAuthenticated)
username = HttpContext.Current.User.Identity.Name;
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
EnrolResponse response = DeviceBI.DeviceEnrol.Enrol(dbContext, username, request);
dbContext.SaveChanges();
EnrolResponse response = DeviceBI.DeviceEnrol.Enrol(database, username, request);
database.SaveChanges();
return response;
}
}
@@ -40,14 +42,15 @@ namespace Disco.BI.Extensions
if (username == null)
throw new InvalidOperationException("Unauthenticated Http Context");
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
User user = UserBI.UserCache.GetUser(username, dbContext, true);
AuthorizationToken token = UserService.GetAuthorization(username, database, true);
WhoAmIResponse response = new WhoAmIResponse()
{
Username = user.Id,
DisplayName = user.DisplayName,
Type = user.Type
Username = token.User.UserId,
DisplayName = token.User.DisplayName,
Type = token.Has(Claims.ComputerAccount) ? "Computer Account" : "User Account"
};
return response;
}
@@ -58,10 +61,10 @@ namespace Disco.BI.Extensions
if (HttpContext.Current == null)
throw new PlatformNotSupportedException("This function can only be accessed from within ASP.NET");
using (DiscoDataContext dbContext = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
MacEnrolResponse response = DeviceBI.DeviceEnrol.MacEnrol(dbContext, request, false);
dbContext.SaveChanges();
MacEnrolResponse response = DeviceBI.DeviceEnrol.MacEnrol(database, request, false);
database.SaveChanges();
return response;
}
}
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.BI.Interop.ActiveDirectory;
using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users;
using System;
using System.Linq;
namespace Disco.BI.Extensions
{
@@ -17,36 +17,57 @@ namespace Disco.BI.Extensions
public static bool CanCreateJob(this Device d)
{
if (!JobActionExtensions.CanCreate())
return false;
return !d.IsDecommissioned();
}
public static bool CanUpdateAssignment(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AssignUser))
return false;
return !d.IsDecommissioned();
}
public static bool CanUpdateDeviceProfile(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Properties.DeviceProfile))
return false;
return !d.IsDecommissioned();
}
public static bool CanUpdateDeviceBatch(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Properties.DeviceBatch))
return false;
return !d.IsDecommissioned();
}
public static bool CanUpdateTrustEnrol(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AllowUnauthenticatedEnrol))
return false;
return !d.IsDecommissioned() && !d.AllowUnauthenticatedEnrol;
}
public static bool CanUpdateUntrustEnrol(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.AllowUnauthenticatedEnrol))
return false;
return !d.IsDecommissioned() && d.AllowUnauthenticatedEnrol;
}
#region Decommission
public static bool CanDecommission(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Decommission))
return false;
if (d.DecommissionedDate.HasValue)
return false; // Already Decommissioned
@@ -58,18 +79,19 @@ namespace Disco.BI.Extensions
return true;
}
public static void OnDecommission(this Device d)
public static void OnDecommission(this Device d, Disco.Models.Repository.DecommissionReasons Reason)
{
if (!d.CanDecommission())
throw new InvalidOperationException("Decommission of Device is Denied");
d.DecommissionedDate = DateTime.Now;
d.DecommissionReason = Reason;
// Disable AD Account
if (d.ComputerName != null)
if (d.DeviceDomainId != null)
{
var adAccount = d.ActiveDirectoryAccount();
if (adAccount != null)
if (adAccount != null && !adAccount.IsCriticalSystemObject)
{
adAccount.DisableAccount();
}
@@ -79,6 +101,9 @@ namespace Disco.BI.Extensions
#region Recommission
public static bool CanRecommission(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Recommission))
return false;
return d.DecommissionedDate.HasValue;
}
public static void OnRecommission(this Device d)
@@ -87,12 +112,13 @@ namespace Disco.BI.Extensions
throw new InvalidOperationException("Recommission of Device is Denied");
d.DecommissionedDate = null;
d.DecommissionReason = null;
// Enable AD Account
if (d.ComputerName != null)
if (d.DeviceDomainId != null)
{
var adAccount = d.ActiveDirectoryAccount();
if (adAccount != null)
if (adAccount != null && !adAccount.IsCriticalSystemObject)
{
adAccount.EnableAccount();
}
@@ -103,17 +129,20 @@ namespace Disco.BI.Extensions
#region Delete
public static bool CanDelete(this Device d)
{
if (!UserService.CurrentAuthorization.Has(Claims.Device.Actions.Delete))
return false;
return d.DecommissionedDate.HasValue;
}
public static void OnDelete(this Device d, DiscoDataContext dbContext)
public static void OnDelete(this Device d, DiscoDataContext Database)
{
// Delete Jobs
foreach (Job j in dbContext.Jobs.Where(i => i.DeviceSerialNumber == d.SerialNumber))
foreach (Job j in Database.Jobs.Where(i => i.DeviceSerialNumber == d.SerialNumber))
{
if (j.UserId == null)
{ // No User associated, thus must Delete whole Job
if (j.CanDelete())
j.OnDelete(dbContext);
j.OnDelete(Database);
else
throw new InvalidOperationException(string.Format("Deletion of Device is Denied (See Job# {0})", j.Id));
}
@@ -126,35 +155,35 @@ namespace Disco.BI.Extensions
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = UserBI.UserCache.CurrentUser.Id,
TechUserId = UserService.CurrentUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Device Deleted{0}{0}Serial Number: {1}{0}Computer Name: {2}{0}Model: {3}{0}Profile: {4}",
Environment.NewLine, d.SerialNumber, d.ComputerName, d.DeviceModel, d.DeviceProfile)
Environment.NewLine, d.SerialNumber, d.DeviceDomainId, d.DeviceModel, d.DeviceProfile)
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
}
}
// Disable Wireless Certificates
foreach (var wc in dbContext.DeviceCertificates.Where(i => i.DeviceSerialNumber == d.SerialNumber))
foreach (var wc in Database.DeviceCertificates.Where(i => i.DeviceSerialNumber == d.SerialNumber))
{
wc.DeviceSerialNumber = null;
wc.Enabled = false;
}
// Delete Device Details
foreach (var dd in dbContext.DeviceDetails.Where(i => i.DeviceSerialNumber == d.SerialNumber))
dbContext.DeviceDetails.Remove(dd);
foreach (var dd in Database.DeviceDetails.Where(i => i.DeviceSerialNumber == d.SerialNumber))
Database.DeviceDetails.Remove(dd);
// Delete Device Attachments
foreach (var da in dbContext.DeviceAttachments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
foreach (var da in Database.DeviceAttachments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
{
da.RepositoryDelete(dbContext);
dbContext.DeviceAttachments.Remove(da);
da.RepositoryDelete(Database);
Database.DeviceAttachments.Remove(da);
}
// Delete Device User Assignments
foreach (var dua in dbContext.DeviceUserAssignments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
dbContext.DeviceUserAssignments.Remove(dua);
foreach (var dua in Database.DeviceUserAssignments.Where(i => i.DeviceSerialNumber == d.SerialNumber))
Database.DeviceUserAssignments.Remove(dua);
dbContext.Devices.Remove(d);
Database.Devices.Remove(d);
}
#endregion
}
@@ -4,28 +4,33 @@ using System.Linq;
using System.Text;
using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
public static class DeviceBatchExtensions
{
public static bool CanDelete(this DeviceBatch db, DiscoDataContext dbContext)
public static bool CanDelete(this DeviceBatch db, DiscoDataContext Database)
{
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceBatch.Delete))
return false;
// Can't Delete if Contains Devices
var deviceCount = dbContext.Devices.Count(d => d.DeviceBatchId == db.Id);
var deviceCount = Database.Devices.Count(d => d.DeviceBatchId == db.Id);
if (deviceCount > 0)
return false;
return true;
}
public static void Delete(this DeviceBatch db, DiscoDataContext dbContext)
public static void Delete(this DeviceBatch db, DiscoDataContext Database)
{
if (!db.CanDelete(dbContext))
if (!db.CanDelete(Database))
throw new InvalidOperationException("The state of this Device Batch doesn't allow it to be deleted");
// Delete Batch
dbContext.DeviceBatches.Remove(db);
Database.DeviceBatches.Remove(db);
}
}
}
@@ -11,16 +11,10 @@ namespace Disco.BI.Extensions
public static class DeviceCertificateExtensions
{
public static Tuple<DeviceCertificate, List<string>> AllocateCertificate(this Device device, DiscoDataContext dbContext)
public static Tuple<DeviceCertificate, List<string>> AllocateCertificate(this Device device, DiscoDataContext Database)
{
if (!string.IsNullOrEmpty(device.DeviceProfile.CertificateProviderId))
{
// REMOVED 2012-07-18 G# - Plugin is responsible for checking
//var deviceCertificates = dbContext.DeviceCertificates.Where(c =>
// c.DeviceSerialNumber == device.SerialNumber &&
// c.ProviderId == device.DeviceProfile.CertificateProviderId &&
// c.Enabled == true).ToList();
// Load Plugin
PluginFeatureManifest featureManifest = Plugins.GetPluginFeature(device.DeviceProfile.CertificateProviderId, typeof(CertificateProviderFeature));
@@ -32,7 +26,7 @@ namespace Disco.BI.Extensions
// return new Tuple<DeviceCertificate, List<string>>(deviceCertificates[0], providerPlugin.RemoveExistingCertificateNames());
//else
return providerFeature.AllocateCertificate(dbContext, device);
return providerFeature.AllocateCertificate(Database, device);
}
}
@@ -0,0 +1,162 @@
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Extensions
{
public static class DeviceDetailExtensions
{
#region Helpers
private static string GetDetail(this IEnumerable<DeviceDetail> details, string Scope, string Key)
{
if (details == null)
throw new ArgumentNullException("details");
if (string.IsNullOrEmpty(Scope))
throw new ArgumentNullException("Scope");
if (string.IsNullOrEmpty(Key))
throw new ArgumentNullException("Key");
var detail = details.Where(d => d.Key == Key).FirstOrDefault();
if (detail == null)
return null;
else
return detail.Value;
}
private static void SetDetail(this Device device, string Scope, string Key, string Value)
{
if (device == null)
throw new ArgumentNullException("device");
if (string.IsNullOrEmpty(Scope))
throw new ArgumentNullException("Scope");
if (string.IsNullOrEmpty(Key))
throw new ArgumentNullException("Key");
var detail = device.DeviceDetails.Where(d => d.Scope == Scope && d.Key == Key).FirstOrDefault();
// No Detail Stored & Set to Null
if (detail == null && Value == null)
return;
if (detail == null)
{
detail = new DeviceDetail()
{
DeviceSerialNumber = device.SerialNumber,
Scope = Scope,
Key = Key,
Value = Value
};
device.DeviceDetails.Add(detail);
}
if (detail.Value != Value)
{
if (Value == null)
{
device.DeviceDetails.Remove(detail);
}
else
{
detail.Value = Value;
}
}
}
#endregion
#region LanMacAddress
/// <summary>
/// Gets the LanMacAddress Device Detail Value
/// </summary>
/// <returns>The LanMacAddress or null</returns>
public static string LanMacAddress(this IEnumerable<DeviceDetail> details)
{
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress);
}
/// <summary>
/// Sets the LanMacAddress Device Detail Value
/// </summary>
public static void LanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string LanMacAddress)
{
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyLanMacAddress, LanMacAddress);
}
#endregion
#region WLanMacAddress
/// <summary>
/// Gets the WLanMacAddress Device Detail Value
/// </summary>
/// <returns>The WLanMacAddress or null</returns>
public static string WLanMacAddress(this IEnumerable<DeviceDetail> details)
{
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress);
}
/// <summary>
/// Sets the WLanMacAddress Device Detail Value
/// </summary>
public static void WLanMacAddress(this IEnumerable<DeviceDetail> details, Device device, string WLanMacAddress)
{
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyWLanMacAddress, WLanMacAddress);
}
#endregion
#region ACAdapter
/// <summary>
/// Gets the ACAdapter Device Detail Value
/// </summary>
/// <returns>The ACAdapter or null</returns>
public static string ACAdapter(this IEnumerable<DeviceDetail> details)
{
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter);
}
/// <summary>
/// Sets the ACAdapter Device Detail Value
/// </summary>
public static void ACAdapter(this IEnumerable<DeviceDetail> details, Device device, string ACAdapter)
{
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyACAdapter, ACAdapter);
}
#endregion
#region Battery
/// <summary>
/// Gets the Battery Device Detail Value
/// </summary>
/// <returns>The Battery or null</returns>
public static string Battery(this IEnumerable<DeviceDetail> details)
{
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery);
}
/// <summary>
/// Sets the Battery Device Detail Value
/// </summary>
public static void Battery(this IEnumerable<DeviceDetail> details, Device device, string Battery)
{
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyBattery, Battery);
}
#endregion
#region Keyboard
/// <summary>
/// Gets the Keyboard Device Detail Value
/// </summary>
/// <returns>The Keyboard or null</returns>
public static string Keyboard(this IEnumerable<DeviceDetail> details)
{
return details.GetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard);
}
/// <summary>
/// Sets the Keyboard Device Detail Value
/// </summary>
public static void Keyboard(this IEnumerable<DeviceDetail> details, Device device, string Keyboard)
{
device.SetDetail(DeviceDetail.ScopeHardware, DeviceDetail.HardwareKeyKeyboard, Keyboard);
}
#endregion
}
}
+95 -36
View File
@@ -1,5 +1,4 @@
using System.Linq;
using Disco.BI.Interop.ActiveDirectory;
using Disco.Data.Configuration;
using Disco.Data.Repository;
using Disco.Models.BI.DocumentTemplates;
@@ -7,15 +6,20 @@ using Disco.Models.Repository;
using System.Collections.Generic;
using System;
using System.IO;
using Disco.Models.Interop.ActiveDirectory;
using Disco.Services.Users;
using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory;
namespace Disco.BI.Extensions
{
public static class DeviceExtensions
{
public static string ComputerNameRender(this Device device, DiscoDataContext context)
public static string ComputerNameRender(this Device device, DiscoDataContext Database, ADDomain Domain)
{
if (Domain == null)
throw new ArgumentNullException("Domain");
DeviceProfile deviceProfile = device.DeviceProfile;
Expressions.Expression computerNameTemplateExpression = null;
computerNameTemplateExpression = Expressions.ExpressionCache.GetValue(DeviceProfileExtensions.ComputerNameExpressionCacheModule, deviceProfile.Id.ToString(), () =>
@@ -24,7 +28,7 @@ namespace Disco.BI.Extensions
//return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.Configuration(context).ComputerNameTemplate, 0);
return Expressions.Expression.TokenizeSingleDynamic(null, deviceProfile.ComputerNameTemplate, 0);
});
System.Collections.IDictionary evaluatorVariables = Expressions.Expression.StandardVariables(null, context, UserBI.UserCache.CurrentUser, System.DateTime.Now, null);
System.Collections.IDictionary evaluatorVariables = Expressions.Expression.StandardVariables(null, Database, UserService.CurrentUser, System.DateTime.Now, null);
string rendered;
try
{
@@ -38,30 +42,31 @@ namespace Disco.BI.Extensions
{
throw new System.InvalidOperationException("The rendered computer name would be invalid or longer than 24 characters");
}
return rendered.ToString();
return string.Format(@"{0}\{1}", Domain.NetBiosName, rendered);
}
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Context, User User, System.DateTime TimeStamp)
public static System.Collections.Generic.List<DocumentTemplate> AvailableDocumentTemplates(this Device d, DiscoDataContext Database, User User, System.DateTime TimeStamp)
{
List<DocumentTemplate> ats = Context.DocumentTemplates
List<DocumentTemplate> ats = Database.DocumentTemplates
.Where(at => at.Scope == Disco.Models.Repository.DocumentTemplate.DocumentTemplateScopes.Device).ToList();
return ats.Where(at => at.FilterExpressionMatches(d, Context, User, TimeStamp, DocumentState.DefaultState())).ToList();
return ats.Where(at => at.FilterExpressionMatches(d, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
}
public static bool UpdateLastNetworkLogonDate(this Device Device)
{
return ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDate(Device);
return Disco.Services.Interop.ActiveDirectory.ADNetworkLogonDatesUpdateTask.UpdateLastNetworkLogonDate(Device);
}
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext dbContext, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
public static DeviceAttachment CreateAttachment(this Device Device, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
{
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
DeviceAttachment da = new DeviceAttachment()
{
DeviceSerialNumber = Device.SerialNumber,
TechUserId = CreatorUser.Id,
TechUserId = CreatorUser.UserId,
Filename = Filename,
MimeType = MimeType,
Timestamp = DateTime.Now,
@@ -71,20 +76,20 @@ namespace Disco.BI.Extensions
if (DocumentTemplate != null)
da.DocumentTemplateId = DocumentTemplate.Id;
dbContext.DeviceAttachments.Add(da);
dbContext.SaveChanges();
Database.DeviceAttachments.Add(da);
Database.SaveChanges();
da.SaveAttachment(dbContext, Content);
da.SaveAttachment(Database, Content);
Content.Position = 0;
if (PdfThumbnail == null)
da.GenerateThumbnail(dbContext, Content);
da.GenerateThumbnail(Database, Content);
else
da.SaveThumbnailAttachment(dbContext, PdfThumbnail);
da.SaveThumbnailAttachment(Database, PdfThumbnail);
return da;
}
public static Device AddOffline(this Device d, DiscoDataContext dbContext)
public static Device AddOffline(this Device d, DiscoDataContext Database)
{
// Just Include:
// - Serial Number
@@ -93,17 +98,31 @@ namespace Disco.BI.Extensions
// - Assigned User Id
// - Batch
// Enforce Authorization
var auth = UserService.CurrentAuthorization;
if (!auth.Has(Claims.Device.Properties.AssetNumber))
d.AssetNumber = null;
if (!auth.Has(Claims.Device.Properties.Location))
d.Location = null;
if (!auth.Has(Claims.Device.Properties.DeviceBatch))
d.DeviceBatchId = null;
if (!auth.Has(Claims.Device.Properties.DeviceProfile))
d.DeviceProfileId = Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId;
if (!auth.Has(Claims.Device.Actions.AssignUser))
d.AssignedUserId = null;
// Batch
DeviceBatch db = default(DeviceBatch);
if (d.DeviceBatchId.HasValue)
db = dbContext.DeviceBatches.Find(d.DeviceBatchId.Value);
db = Database.DeviceBatches.Find(d.DeviceBatchId.Value);
// Default Device Model
DeviceModel dm = default(DeviceModel);
if (db != null && db.DefaultDeviceModelId.HasValue)
dm = dbContext.DeviceModels.Find(db.DefaultDeviceModelId); // From Batch
dm = Database.DeviceModels.Find(db.DefaultDeviceModelId); // From Batch
else
dm = dbContext.DeviceModels.Find(1); // Default
dm = Database.DeviceModels.Find(1); // Default
Device d2 = new Device()
{
@@ -112,7 +131,7 @@ namespace Disco.BI.Extensions
Location = d.Location,
CreatedDate = DateTime.Now,
DeviceProfileId = d.DeviceProfileId,
DeviceProfile = dbContext.DeviceProfiles.Find(d.DeviceProfileId),
DeviceProfile = Database.DeviceProfiles.Find(d.DeviceProfileId),
AllowUnauthenticatedEnrol = true,
DeviceModelId = dm.Id,
DeviceModel = dm,
@@ -120,22 +139,22 @@ namespace Disco.BI.Extensions
DeviceBatch = db
};
dbContext.Devices.Add(d2);
Database.Devices.Add(d2);
if (!string.IsNullOrEmpty(d.AssignedUserId))
{
User u = UserBI.UserCache.GetUser(d.AssignedUserId, dbContext, true);
d2.AssignDevice(dbContext, u);
User u = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(d.AssignedUserId), Database, true);
d2.AssignDevice(Database, u);
}
return d2;
}
public static DeviceUserAssignment AssignDevice(this Device d, DiscoDataContext dbContext, User u)
public static DeviceUserAssignment AssignDevice(this Device d, DiscoDataContext Database, User u)
{
DeviceUserAssignment newDua = default(DeviceUserAssignment);
// Mark existing assignments as Unassigned
foreach (var dua in dbContext.DeviceUserAssignments.Where(m => m.DeviceSerialNumber == d.SerialNumber && !m.UnassignedDate.HasValue))
foreach (var dua in Database.DeviceUserAssignments.Where(m => m.DeviceSerialNumber == d.SerialNumber && !m.UnassignedDate.HasValue))
dua.UnassignedDate = DateTime.Now;
if (u != null)
@@ -144,12 +163,12 @@ namespace Disco.BI.Extensions
newDua = new DeviceUserAssignment()
{
DeviceSerialNumber = d.SerialNumber,
AssignedUserId = u.Id,
AssignedUserId = u.UserId,
AssignedDate = DateTime.Now
};
dbContext.DeviceUserAssignments.Add(newDua);
Database.DeviceUserAssignments.Add(newDua);
d.AssignedUserId = u.Id;
d.AssignedUserId = u.UserId;
d.AssignedUser = u;
}
else
@@ -158,9 +177,9 @@ namespace Disco.BI.Extensions
}
// Update AD Account
if (!string.IsNullOrEmpty(d.ComputerName) && d.ComputerName.Length <= 24)
if (!string.IsNullOrEmpty(d.DeviceDomainId))
{
var adMachineAccount = Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(d.ComputerName);
var adMachineAccount = ActiveDirectory.RetrieveADMachineAccount(d.DeviceDomainId);
if (adMachineAccount != null)
{
adMachineAccount.SetDescription(d);
@@ -170,18 +189,58 @@ namespace Disco.BI.Extensions
return newDua;
}
public static ActiveDirectoryMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
public static ADMachineAccount ActiveDirectoryAccount(this Device Device, params string[] AdditionalProperties)
{
if (!string.IsNullOrEmpty(Device.ComputerName))
return Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(Device.ComputerName, AdditionalProperties: AdditionalProperties);
if (!string.IsNullOrEmpty(Device.DeviceDomainId))
return ActiveDirectory.RetrieveADMachineAccount(Device.DeviceDomainId, AdditionalProperties: AdditionalProperties);
else
return null;
}
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons r)
{
switch (r)
{
case DecommissionReasons.EndOfLife:
return "End of Life";
case DecommissionReasons.Sold:
return "Sold";
case DecommissionReasons.Stolen:
return "Stolen";
case DecommissionReasons.Lost:
return "Lost";
case DecommissionReasons.Damaged:
return "Damaged";
case DecommissionReasons.Donated:
return "Donated";
default:
return "Unknown";
}
}
public static string ReasonMessage(this Disco.Models.Repository.DecommissionReasons? r)
{
if (!r.HasValue)
return "Not Decommissioned";
return r.Value.ReasonMessage();
}
public static string StatusCode(this Device Device)
{
if (Device.DecommissionedDate.HasValue)
return "Decommissioned";
if (!Device.EnrolledDate.HasValue)
return "NotEnrolled";
return "Active";
}
public static string Status(this Device Device)
{
if (Device.DecommissionedDate.HasValue)
return "Decommissioned";
return string.Format("Decommissioned ({0})", Device.DecommissionReason.ReasonMessage());
if (!Device.EnrolledDate.HasValue)
return "Not Enrolled";
@@ -6,6 +6,8 @@ using Disco.Models.Repository;
using System.IO;
using System.Drawing;
using Disco.Data.Repository;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
@@ -73,22 +75,24 @@ namespace Disco.BI.Extensions
}
#region Actions
// Added 2012-11-26 G# - Need ability to delete Device Models
public static bool CanDelete(this DeviceModel dm, DiscoDataContext dbContext)
public static bool CanDelete(this DeviceModel dm, DiscoDataContext Database)
{
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceModel.Delete))
return false;
// Can't Delete Default Model (Id: 1)
if (dm.Id == 1)
return false;
// Can't Delete if Contains Devices
if (dbContext.Devices.Count(d => d.DeviceModelId == dm.Id) > 0)
if (Database.Devices.Count(d => d.DeviceModelId == dm.Id) > 0)
return false;
return true;
}
public static void Delete(this DeviceModel dm, DiscoDataContext dbContext)
public static void Delete(this DeviceModel dm, DiscoDataContext Database)
{
if (!dm.CanDelete(dbContext))
if (!dm.CanDelete(Database))
throw new InvalidOperationException("The state of this Device Model doesn't allow it to be deleted");
// Delete Image
@@ -97,13 +101,13 @@ namespace Disco.BI.Extensions
File.Delete(deviceModelImagePath);
// Delete any Device Model Components
foreach (var deviceModelComponent in dbContext.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList())
foreach (var deviceModelComponent in Database.DeviceComponents.Where(dc => dc.DeviceModelId == dm.Id).ToList())
{
dbContext.DeviceComponents.Remove(deviceModelComponent);
Database.DeviceComponents.Remove(deviceModelComponent);
}
// Delete Model
dbContext.DeviceModels.Remove(dm);
Database.DeviceModels.Remove(dm);
}
// End Added 2012-11-26 G#
#endregion
@@ -6,6 +6,8 @@ using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.Data.Configuration.Modules;
using Disco.Models.BI.Config;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
@@ -18,11 +20,11 @@ namespace Disco.BI.Extensions
Expressions.ExpressionCache.InvalidateKey(ComputerNameExpressionCacheModule, deviceProfile.Id.ToString());
}
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext dbContext)
public static OrganisationAddress DefaultOrganisationAddressDetails(this DeviceProfile deviceProfile, DiscoDataContext Database)
{
if (deviceProfile.DefaultOrganisationAddress.HasValue)
{
return dbContext.DiscoConfiguration.OrganisationAddresses.GetAddress(deviceProfile.DefaultOrganisationAddress.Value);
return Database.DiscoConfiguration.OrganisationAddresses.GetAddress(deviceProfile.DefaultOrganisationAddress.Value);
}
else
{
@@ -30,38 +32,35 @@ namespace Disco.BI.Extensions
}
}
public static bool CanDelete(this DeviceProfile dp, DiscoDataContext dbContext)
public static bool CanDelete(this DeviceProfile dp, DiscoDataContext Database)
{
if (!UserService.CurrentAuthorization.Has(Claims.Config.DeviceProfile.Delete))
return false;
// Can't Delete Default Profile (Id: 1)
if (dp.Id == 1)
return false;
// Can't Delete if Contains Devices
if (dbContext.Devices.Count(d => d.DeviceProfileId == dp.Id) > 0)
if (Database.Devices.Count(d => d.DeviceProfileId == dp.Id) > 0)
return false;
return true;
}
public static void Delete(this DeviceProfile dp, DiscoDataContext dbContext)
public static void Delete(this DeviceProfile dp, DiscoDataContext Database)
{
if (!dp.CanDelete(dbContext))
if (!dp.CanDelete(Database))
throw new InvalidOperationException("The state of this Device Profile doesn't allow it to be deleted");
// Update Defaults
if (dbContext.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId == dp.Id)
dbContext.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId = 1;
if (dbContext.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId == dp.Id)
dbContext.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId = 1;
if (Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId == dp.Id)
Database.DiscoConfiguration.DeviceProfiles.DefaultDeviceProfileId = 1;
if (Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId == dp.Id)
Database.DiscoConfiguration.DeviceProfiles.DefaultAddDeviceOfflineDeviceProfileId = 1;
// Delete Profile
dbContext.DeviceProfiles.Remove(dp);
Database.DeviceProfiles.Remove(dp);
}
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
//public static DeviceProfileConfiguration Configuration(this DeviceProfile dp, DiscoDataContext dbContext)
//{
// return dbContext.DiscoConfiguration.DeviceProfiles.DeviceProfile(dp);
//}
}
}
@@ -19,13 +19,13 @@ namespace Disco.BI.Extensions
{
private const string DocumentTemplateExpressionCacheTemplate = "DocumentTemplate_{0}";
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext dbContext)
public static string RepositoryFilename(this DocumentTemplate dt, DiscoDataContext Database)
{
return System.IO.Path.Combine(DataStore.CreateLocation(dbContext, "DocumentTemplates"), string.Format("{0}.pdf", dt.Id));
return System.IO.Path.Combine(DataStore.CreateLocation(Database, "DocumentTemplates"), string.Format("{0}.pdf", dt.Id));
}
public static string SavePdfTemplate(this DocumentTemplate dt, DiscoDataContext dbContext, Stream TemplateFile)
public static string SavePdfTemplate(this DocumentTemplate dt, DiscoDataContext Database, Stream TemplateFile)
{
string filePath = dt.RepositoryFilename(dbContext);
string filePath = dt.RepositoryFilename(Database);
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
TemplateFile.CopyTo(fs);
@@ -39,14 +39,14 @@ namespace Disco.BI.Extensions
return Interop.Pdf.PdfImporter.GetPageImages(pdfReader, PageNumber);
}
public static ConcurrentDictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext dbContext)
public static ConcurrentDictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
{
string cacheModuleKey = string.Format(DocumentTemplateExpressionCacheTemplate, dt.Id);
var module = Expressions.ExpressionCache.GetModule(cacheModuleKey);
if (module == null)
{
// Cache
string templateFilename = dt.RepositoryFilename(dbContext);
string templateFilename = dt.RepositoryFilename(Database);
PdfReader pdfReader = new PdfReader(templateFilename);
int pdfFieldOrdinal = 0;
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
@@ -61,21 +61,21 @@ namespace Disco.BI.Extensions
return module;
}
public static List<BI.Expressions.Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext dbContext)
public static List<BI.Expressions.Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
{
return dt.PdfExpressionsFromCache(dbContext).Values.OrderBy(e => e.Ordinal).ToList();
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
}
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext dbContext, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
{
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, dbContext, CreatorUser, Timestamp, DataObjectsIds);
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjectsIds);
}
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext dbContext, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
public static System.IO.Stream GeneratePdfBulk(this DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
{
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, dbContext, CreatorUser, Timestamp, DataObjects);
return Interop.Pdf.PdfGenerator.GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
}
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext dbContext, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
public static System.IO.Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
{
return Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, dbContext, Data, CreatorUser, TimeStamp, State, FlattenFields);
return Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Data, CreatorUser, TimeStamp, State, FlattenFields);
}
public static Expression FilterExpressionFromCache(this DocumentTemplate dt)
@@ -86,12 +86,12 @@ namespace Disco.BI.Extensions
{
ExpressionCache.InvalidateKey("DocumentTemplateFilterExpression", dt.Id);
}
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext DataContext, User User, System.DateTime TimeStamp, DocumentState State)
public static bool FilterExpressionMatches(this DocumentTemplate dt, object Data, DiscoDataContext Database, User User, System.DateTime TimeStamp, DocumentState State)
{
if (!string.IsNullOrEmpty(dt.FilterExpression))
{
Expression compiledExpression = dt.FilterExpressionFromCache();
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, DataContext, User, TimeStamp, State);
System.Collections.IDictionary evaluatorVariables = Expression.StandardVariables(dt, Database, User, TimeStamp, State);
try
{
object er = compiledExpression.EvaluateFirst<object>(Data, evaluatorVariables);
@@ -136,7 +136,7 @@ namespace Disco.BI.Extensions
if (!(Data is User))
throw new ArgumentException("This Document Template is configured for Users only", "Data");
User d3 = (User)Data;
return d3.Id;
return d3.UserId;
default:
throw new InvalidOperationException("Invalid Document Template Scope");
}
@@ -170,14 +170,14 @@ namespace Disco.BI.Extensions
Page
);
}
public static List<RectangleF> QRCodeLocations(this DocumentTemplate dt, DiscoDataContext dbContext)
public static List<RectangleF> QRCodeLocations(this DocumentTemplate dt, DiscoDataContext Database)
{
return DocumentTemplateBI.DocumentTemplateQRCodeLocationCache.GetLocations(dt, dbContext);
return DocumentTemplateBI.DocumentTemplateQRCodeLocationCache.GetLocations(dt, Database);
}
public static void Delete(this DocumentTemplate dt, DiscoDataContext Context)
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
{
// Find & Rename all references
foreach (DeviceAttachment a in Context.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id))
foreach (DeviceAttachment a in Database.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id))
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
@@ -185,7 +185,7 @@ namespace Disco.BI.Extensions
a.DocumentTemplateId = null;
a.DocumentTemplate = null;
}
foreach (JobAttachment a in Context.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id))
foreach (JobAttachment a in Database.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id))
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
@@ -193,7 +193,7 @@ namespace Disco.BI.Extensions
a.DocumentTemplateId = null;
a.DocumentTemplate = null;
}
foreach (UserAttachment a in Context.UserAttachments.Where(a => a.DocumentTemplateId == dt.Id))
foreach (UserAttachment a in Database.UserAttachments.Where(a => a.DocumentTemplateId == dt.Id))
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
@@ -206,7 +206,7 @@ namespace Disco.BI.Extensions
dt.JobSubTypes.Clear();
// Delete Template
string templateRepositoryFilename = dt.RepositoryFilename(Context);
string templateRepositoryFilename = dt.RepositoryFilename(Database);
if (System.IO.File.Exists(templateRepositoryFilename))
System.IO.File.Delete(templateRepositoryFilename);
@@ -214,7 +214,7 @@ namespace Disco.BI.Extensions
dt.FilterExpressionInvalidateCache();
// Delete Document Template from Repository
Context.DocumentTemplates.Remove(dt);
Database.DocumentTemplates.Remove(dt);
}
}
}
+153 -65
View File
@@ -6,15 +6,32 @@ using Disco.Models.BI.Config;
using Disco.Models.Repository;
using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.WarrantyProvider;
using Disco.Services.Users;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
public static class JobActionExtensions
{
#region Create
public static bool CanCreate()
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Create))
return false;
if (!UserService.CurrentAuthorization.HasAny(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt))
return false;
return true;
}
#endregion
#region Device Held
public static bool CanDeviceHeld(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceHeld))
return false;
return (!j.ClosedDate.HasValue) && (j.DeviceSerialNumber != null) &&
(!j.DeviceHeld.HasValue || j.DeviceReturnedDate.HasValue);
}
@@ -24,7 +41,7 @@ namespace Disco.BI.Extensions
throw new InvalidOperationException("Holding Device was Denied");
j.DeviceHeld = DateTime.Now;
j.DeviceHeldTechUserId = Technician.Id;
j.DeviceHeldTechUserId = Technician.UserId;
j.DeviceReadyForReturn = null;
j.DeviceReadyForReturnTechUserId = null;
j.DeviceReturnedDate = null;
@@ -35,6 +52,9 @@ namespace Disco.BI.Extensions
#region Device Ready for Return
public static bool CanDeviceReadyForReturn(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReadyForReturn))
return false;
return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue &&
!j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue;
}
@@ -44,13 +64,16 @@ namespace Disco.BI.Extensions
throw new InvalidOperationException("Device Ready for Return was Denied");
j.DeviceReadyForReturn = DateTime.Now;
j.DeviceReadyForReturnTechUserId = Technician.Id;
j.DeviceReadyForReturnTechUserId = Technician.UserId;
}
#endregion
#region Device Returned
public static bool CanDeviceReturned(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.DeviceReturned))
return false;
return (!j.ClosedDate.HasValue) && j.DeviceHeld.HasValue &&
!j.DeviceReturnedDate.HasValue;
}
@@ -60,16 +83,19 @@ namespace Disco.BI.Extensions
throw new InvalidOperationException("Device Return was Denied");
j.DeviceReturnedDate = DateTime.Now;
j.DeviceReturnedTechUserId = Technician.Id;
j.DeviceReturnedTechUserId = Technician.UserId;
}
#endregion
#region Waiting For User Action
public static bool CanWaitingForUserAction(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.WaitingForUserAction))
return false;
return !j.ClosedDate.HasValue && (j.UserId != null) && !j.WaitingForUserAction.HasValue;
}
public static void OnWaitingForUserAction(this Job j, DiscoDataContext dbContext, User Technician, string Reason)
public static void OnWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Reason)
{
if (!j.CanWaitingForUserAction())
throw new InvalidOperationException("Waiting for User Action was Denied");
@@ -80,20 +106,23 @@ namespace Disco.BI.Extensions
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = Technician.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Waiting on User Action{0}Reason: {1}", Environment.NewLine, Reason)
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
}
#endregion
#region Not Waiting For User Action
public static bool CanNotWaitingForUserAction(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NotWaitingForUserAction))
return false;
return j.WaitingForUserAction.HasValue;
}
public static void OnNotWaitingForUserAction(this Job j, DiscoDataContext dbContext, User Technician, string Resolution)
public static void OnNotWaitingForUserAction(this Job j, DiscoDataContext Database, User Technician, string Resolution)
{
if (!j.CanNotWaitingForUserAction())
throw new InvalidOperationException("Not Waiting for User Action was Denied");
@@ -104,35 +133,38 @@ namespace Disco.BI.Extensions
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = Technician.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("User Action Resolved{0}Resolution: {1}", Environment.NewLine, Resolution)
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
}
#endregion
#region Log Warranty
public static bool CanLogWarranty(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogWarranty))
return false;
return !j.ClosedDate.HasValue &&
(j.DeviceSerialNumber != null) &&
j.JobTypeId == JobType.JobTypeIds.HWar &&
string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference);
!j.JobMetaWarranty.ExternalLoggedDate.HasValue;
}
public static void OnLogWarranty(this Job j, DiscoDataContext dbContext, string FaultDescription, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
public static void OnLogWarranty(this Job j, DiscoDataContext Database, string FaultDescription, PluginFeatureManifest WarrantyProviderDefinition, OrganisationAddress Address, User TechUser, Dictionary<string, string> WarrantyProviderProperties)
{
if (!j.CanLogWarranty())
throw new InvalidOperationException("Log Warranty was Denied");
if (string.IsNullOrWhiteSpace(FaultDescription))
FaultDescription = j.GenerateFaultDescriptionFooter(dbContext, WarrantyProviderDefinition);
FaultDescription = j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition);
else
FaultDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(dbContext, WarrantyProviderDefinition));
FaultDescription = string.Concat(FaultDescription, Environment.NewLine, Environment.NewLine, j.GenerateFaultDescriptionFooter(Database, WarrantyProviderDefinition));
using (WarrantyProviderFeature WarrantyProvider = WarrantyProviderDefinition.CreateInstance<WarrantyProviderFeature>())
{
string providerRef = WarrantyProvider.SubmitJob(dbContext, j, Address, TechUser, FaultDescription, WarrantyProviderProperties);
string providerRef = WarrantyProvider.SubmitJob(Database, j, Address, TechUser, FaultDescription, WarrantyProviderProperties);
j.JobMetaWarranty.ExternalLoggedDate = DateTime.Now;
j.JobMetaWarranty.ExternalName = WarrantyProvider.WarrantyProviderId;
@@ -146,11 +178,11 @@ namespace Disco.BI.Extensions
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = TechUser.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Warranty Claim Submitted{0}{0}Provider: {1}{0}Repair Address: {2}{0}Provider Reference: {3}{0}{0}{4}", Environment.NewLine, WarrantyProvider.Manifest.Name, Address.Name, providerRef, FaultDescription)
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
}
}
#endregion
@@ -158,36 +190,39 @@ namespace Disco.BI.Extensions
#region Convert HWar to HNWar
public static bool CanConvertHWarToHNWar(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ConvertHWarToHNWar))
return false;
return !j.ClosedDate.HasValue && (j.DeviceSerialNumber != null) &&
j.JobTypeId == JobType.JobTypeIds.HWar && string.IsNullOrEmpty(j.JobMetaWarranty.ExternalReference);
}
public static void OnConvertHWarToHNWar(this Job j, DiscoDataContext dbContext)
public static void OnConvertHWarToHNWar(this Job j, DiscoDataContext Database)
{
if (!j.CanConvertHWarToHNWar())
throw new InvalidOperationException("Convert HWar to HNWar was Denied");
var techUser = UserBI.UserCache.CurrentUser;
var techUser = UserService.CurrentUser;
// Remove JobMetaWarranty
if (j.JobMetaWarranty != null)
dbContext.JobMetaWarranties.Remove(j.JobMetaWarranty);
Database.JobMetaWarranties.Remove(j.JobMetaWarranty);
// Add JobMetaNonWarranty
var metaHNWar = new JobMetaNonWarranty() { Job = j };
dbContext.JobMetaNonWarranties.Add(metaHNWar);
Database.JobMetaNonWarranties.Add(metaHNWar);
// Swap Job Sub Types
List<string> jobSubTypes = j.JobSubTypes.Select(jst => jst.Id).ToList();
j.JobSubTypes.Clear();
foreach (var jst in dbContext.JobSubTypes.Where(i => i.JobTypeId == JobType.JobTypeIds.HNWar && jobSubTypes.Contains(i.Id)))
foreach (var jst in Database.JobSubTypes.Where(i => i.JobTypeId == JobType.JobTypeIds.HNWar && jobSubTypes.Contains(i.Id)))
j.JobSubTypes.Add(jst);
// Add Components
var components = dbContext.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var jobComponents = new List<DeviceComponent>();
foreach (var component in components)
{
if (!component.DeviceModelId.HasValue)
if (component.JobSubTypes.Count == 0)
{
jobComponents.Add(component);
}
@@ -210,10 +245,10 @@ namespace Disco.BI.Extensions
}
foreach (var component in jobComponents)
{
dbContext.JobComponents.Add(new JobComponent()
Database.JobComponents.Add(new JobComponent()
{
Job = j,
TechUserId = techUser.Id,
TechUserId = techUser.UserId,
Cost = component.Cost,
Description = component.Description
});
@@ -223,11 +258,11 @@ namespace Disco.BI.Extensions
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = techUser.Id,
TechUserId = techUser.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, dbContext.JobTypes.Find(JobType.JobTypeIds.HWar), dbContext.JobTypes.Find(JobType.JobTypeIds.HNWar))
Comments = string.Format("Job Type Converted{0}From: {1}{0}To: {2}", Environment.NewLine, Database.JobTypes.Find(JobType.JobTypeIds.HWar), Database.JobTypes.Find(JobType.JobTypeIds.HNWar))
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
j.JobTypeId = JobType.JobTypeIds.HNWar;
}
@@ -252,6 +287,9 @@ namespace Disco.BI.Extensions
#region Insurance Claim Form Sent
public static bool CanInsuranceClaimFormSent(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.InsuranceClaimFormSent))
return false;
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
j.JobMetaNonWarranty.IsInsuranceClaim &&
!j.JobMetaInsurance.ClaimFormSentDate.HasValue;
@@ -261,16 +299,19 @@ namespace Disco.BI.Extensions
if (!j.CanInsuranceClaimFormSent())
throw new InvalidOperationException("Insurance Claim Form Sent was Denied");
var techUser = UserBI.UserCache.CurrentUser;
var techUser = UserService.CurrentUser;
j.JobMetaInsurance.ClaimFormSentDate = DateTime.Now;
j.JobMetaInsurance.ClaimFormSentUserId = techUser.Id;
j.JobMetaInsurance.ClaimFormSentUserId = techUser.UserId;
}
#endregion
#region Log Repair
public static bool CanLogRepair(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.LogRepair))
return false;
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
(j.DeviceSerialNumber != null) &&
!j.JobMetaNonWarranty.RepairerLoggedDate.HasValue &&
@@ -292,6 +333,9 @@ namespace Disco.BI.Extensions
#region Repair Complete
public static bool CanRepairComplete(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Properties.NonWarrantyProperties.RepairerCompletedDate))
return false;
return (j.JobTypeId == JobType.JobTypeIds.HNWar) &&
j.JobMetaNonWarranty.RepairerLoggedDate.HasValue &&
!j.JobMetaNonWarranty.RepairerCompletedDate.HasValue;
@@ -306,17 +350,56 @@ namespace Disco.BI.Extensions
#endregion
#region Close
public static bool CanClose(this Job j)
public static void OnCloseNormally(this Job j, User Technician)
{
if (!j.CanCloseNormally())
throw new InvalidOperationException("Close was Denied");
j.ClosedDate = DateTime.Now;
j.ClosedTechUserId = Technician.UserId;
}
private static bool CanCloseNever(this Job j, JobQueueJob IgnoreJobQueueJob = null)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Close))
return true;
if (j.ClosedDate.HasValue)
return false; // Job already Closed
return true; // Job already Closed
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
return false; // Device not returned to User
return true; // Device not returned to User
if (j.WaitingForUserAction.HasValue)
return false; // Job waiting on User Action
return true; // Job waiting on User Action
if (j.JobQueues != null)
{
if (IgnoreJobQueueJob == null)
{
if (j.JobQueues.Any(jqj => !jqj.RemovedDate.HasValue))
return true; // Job associated with a Job Queue
}
else
{
if (j.JobQueues.Any(jqj => jqj.Id != IgnoreJobQueueJob.Id && !jqj.RemovedDate.HasValue))
return true; // Job associated with a Job Queue
}
}
return false;
}
public static bool CanCloseNormally(this Job j)
{
if (j.CanCloseNever())
return false;
return j.CanCloseNormallyInternal();
}
private static bool CanCloseNormallyInternal(this Job j)
{
switch (j.JobTypeId)
{
case JobType.JobTypeIds.HWar:
@@ -339,33 +422,27 @@ namespace Disco.BI.Extensions
return true;
}
public static void OnClose(this Job j, User Technician)
{
if (!j.CanClose())
throw new InvalidOperationException("Close was Denied");
j.ClosedDate = DateTime.Now;
j.ClosedTechUserId = Technician.Id;
public static bool CanCloseJobNormallyAfterRemoved(this JobQueueJob jqj)
{
if (jqj.Job.CanCloseNever(jqj))
return false;
return jqj.Job.CanCloseNormallyInternal();
}
#endregion
#region Force Close
public static bool CanForceClose(this Job j)
public static bool CanCloseForced(this Job j)
{
var canCloseNormally = j.CanClose();
if (canCloseNormally)
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.ForceClose))
return false;
// Check for Override
if (j.ClosedDate.HasValue)
return false; // Job already Closed
if (j.CanCloseNever())
return false;
if (j.DeviceHeld.HasValue && !j.DeviceReturnedDate.HasValue)
return false; // Device not returned to User
if (j.WaitingForUserAction.HasValue)
return false; // Job waiting on User Action
if (j.CanCloseNormally())
return false;
switch (j.JobTypeId)
{
@@ -389,29 +466,32 @@ namespace Disco.BI.Extensions
return false;
}
public static void OnForceClose(this Job j, DiscoDataContext dbContext, User Technician, string Reason)
public static void OnCloseForced(this Job j, DiscoDataContext Database, User Technician, string Reason)
{
if (!j.CanForceClose())
if (!j.CanCloseForced())
throw new InvalidOperationException("Force Close was Denied");
// Write Log
JobLog jobLog = new JobLog()
{
JobId = j.Id,
TechUserId = Technician.Id,
TechUserId = Technician.UserId,
Timestamp = DateTime.Now,
Comments = string.Format("Job Forcibly Closed{0}Reason: {1}", Environment.NewLine, Reason)
};
dbContext.JobLogs.Add(jobLog);
Database.JobLogs.Add(jobLog);
j.ClosedDate = DateTime.Now;
j.ClosedTechUserId = Technician.Id;
j.ClosedTechUserId = Technician.UserId;
}
#endregion
#region Reopen
public static bool CanReopen(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Reopen))
return false;
return j.ClosedDate.HasValue;
}
public static void OnReopen(this Job j)
@@ -427,47 +507,55 @@ namespace Disco.BI.Extensions
#region Delete
public static bool CanDelete(this Job j)
{
if (!UserService.CurrentAuthorization.Has(Claims.Job.Actions.Delete))
return false;
return j.ClosedDate.HasValue;
}
public static void OnDelete(this Job j, DiscoDataContext dbContext)
public static void OnDelete(this Job j, DiscoDataContext Database)
{
// Job Sub Types
j.JobSubTypes.Clear();
// Job Attachments
foreach (var ja in j.JobAttachments.ToArray())
ja.OnDelete(dbContext);
ja.OnDelete(Database);
j.JobAttachments.Clear();
// Job Components
foreach (var jc in j.JobComponents.ToArray())
dbContext.JobComponents.Remove(jc);
Database.JobComponents.Remove(jc);
j.JobComponents.Clear();
// Job Queue Jobs
foreach (var jqj in j.JobQueues.ToArray())
Database.JobQueueJobs.Remove(jqj);
j.JobQueues.Clear();
// Job Logs
foreach (var jl in j.JobLogs.ToArray())
dbContext.JobLogs.Remove(jl);
Database.JobLogs.Remove(jl);
j.JobLogs.Clear();
// Job Meta
if (j.JobMetaInsurance != null)
{
dbContext.JobMetaInsurances.Remove(j.JobMetaInsurance);
Database.JobMetaInsurances.Remove(j.JobMetaInsurance);
j.JobMetaInsurance = null;
}
if (j.JobMetaNonWarranty != null)
{
dbContext.JobMetaNonWarranties.Remove(j.JobMetaNonWarranty);
Database.JobMetaNonWarranties.Remove(j.JobMetaNonWarranty);
j.JobMetaNonWarranty = null;
}
if (j.JobMetaWarranty != null)
{
dbContext.JobMetaWarranties.Remove(j.JobMetaWarranty);
Database.JobMetaWarranties.Remove(j.JobMetaWarranty);
j.JobMetaWarranty = null;
}
// Job
dbContext.Jobs.Remove(j);
Database.Jobs.Remove(j);
}
#endregion
}
+58 -122
View File
@@ -8,20 +8,21 @@ using System.IO;
using Disco.Models.BI.DocumentTemplates;
using Disco.Services.Plugins;
using Disco.Models.BI.Job;
using Disco.Services.Authorization;
namespace Disco.BI.Extensions
{
public static class JobExtensions
{
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext dbContext, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
public static JobAttachment CreateAttachment(this Job Job, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
{
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
JobAttachment ja = new JobAttachment()
{
JobId = Job.Id,
TechUserId = CreatorUser.Id,
TechUserId = CreatorUser.UserId,
Filename = Filename,
MimeType = MimeType,
Timestamp = DateTime.Now,
@@ -31,124 +32,22 @@ namespace Disco.BI.Extensions
if (DocumentTemplate != null)
ja.DocumentTemplateId = DocumentTemplate.Id;
dbContext.JobAttachments.Add(ja);
dbContext.SaveChanges();
Database.JobAttachments.Add(ja);
Database.SaveChanges();
ja.SaveAttachment(dbContext, Content);
ja.SaveAttachment(Database, Content);
Content.Position = 0;
if (PdfThumbnail == null)
ja.GenerateThumbnail(dbContext, Content);
ja.GenerateThumbnail(Database, Content);
else
ja.SaveThumbnailAttachment(dbContext, PdfThumbnail);
ja.SaveThumbnailAttachment(Database, PdfThumbnail);
return ja;
}
public static Tuple<string, string> Status(this Job j)
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext Database, User User, DateTime TimeStamp)
{
var statusId = j.CalculateStatusId();
return new Tuple<string, string>(statusId, JobBI.Utilities.JobStatusDescription(statusId, j));
}
public static JobTableModel.JobTableItemModelIncludeStatus ToJobTableItemModelIncludeStatus(this Job j)
{
var i = new JobTableModel.JobTableItemModelIncludeStatus()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
Location = j.DeviceHeldLocation,
WaitingForUserAction = j.WaitingForUserAction,
DeviceReadyForReturn = j.DeviceReadyForReturn,
DeviceHeld = j.DeviceHeld,
DeviceReturnedDate = j.DeviceReturnedDate
};
if (j.Device != null)
{
i.DeviceSerialNumber = j.DeviceSerialNumber;
i.DeviceModelDescription = j.Device.DeviceModel.Description;
i.DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress;
if (j.JobMetaWarranty != null)
{
i.JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference;
i.JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate;
i.JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName;
}
if (j.JobMetaNonWarranty != null)
{
i.JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate;
i.JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate;
i.JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate;
i.JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate;
i.JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate;
i.JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim;
i.JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName;
if (j.JobMetaInsurance != null)
{
i.JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate;
}
}
}
if (j.User != null)
{
i.UserId = j.UserId;
i.UserDisplayName = j.User.DisplayName;
}
if (j.OpenedTechUser != null)
{
i.OpenedTechUserId = j.OpenedTechUserId;
i.OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName;
}
return i;
}
public static string CalculateStatusId(this Job j)
{
return j.ToJobTableItemModelIncludeStatus().CalculateStatusId();
}
public static string CalculateStatusId(this JobTableModel.JobTableItemModelIncludeStatus j)
{
if (j.ClosedDate.HasValue)
return Job.JobStatusIds.Closed;
if (j.TypeId == JobType.JobTypeIds.HWar)
{
if (!string.IsNullOrEmpty(j.JobMetaWarranty_ExternalReference) && !j.JobMetaWarranty_ExternalCompletedDate.HasValue)
return Job.JobStatusIds.AwaitingWarrantyRepair; // Job Logged - but not marked as completed
}
if (j.TypeId == JobType.JobTypeIds.HNWar)
{
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && !j.JobMetaNonWarranty_RepairerCompletedDate.HasValue)
return Job.JobStatusIds.AwaitingRepairs; // Repairs logged - but not complete
if (j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue && !j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue)
return Job.JobStatusIds.AwaitingAccountingPayment; // Accounting Charge Added, but not paid
if (j.JobMetaNonWarranty_AccountingChargeRequiredDate.HasValue && (!j.JobMetaNonWarranty_AccountingChargePaidDate.HasValue || !j.JobMetaNonWarranty_AccountingChargeAddedDate.HasValue))
return Job.JobStatusIds.AwaitingAccountingCharge; // Accounting Charge Required, but not added or paid
if (j.JobMetaNonWarranty_RepairerLoggedDate.HasValue && j.JobMetaNonWarranty_IsInsuranceClaim.Value && !j.JobMetaInsurance_ClaimFormSentDate.HasValue)
return Job.JobStatusIds.AwaitingInsuranceProcessing; // Is insurance claim, but no Claim Form Sent
}
if (j.WaitingForUserAction.HasValue)
return Job.JobStatusIds.AwaitingUserAction; // Awaiting for User
if (j.DeviceReadyForReturn.HasValue && !j.DeviceReturnedDate.HasValue)
return Job.JobStatusIds.AwaitingDeviceReturn; // Device not returned to User
return Job.JobStatusIds.Open;
}
public static List<DocumentTemplate> AvailableDocumentTemplates(this Job j, DiscoDataContext dbContext, User User, DateTime TimeStamp)
{
var dts = dbContext.DocumentTemplates.Include("JobSubTypes")
var dts = Database.DocumentTemplates.Include("JobSubTypes")
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.Job)
.ToList();
@@ -171,7 +70,7 @@ namespace Disco.BI.Extensions
}
// Evaluate Filters
dts = dts.Where(dt => dt.FilterExpressionMatches(j, dbContext, User, TimeStamp, DocumentState.DefaultState())).ToList();
dts = dts.Where(dt => dt.FilterExpressionMatches(j, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
return dts;
}
@@ -188,7 +87,7 @@ namespace Disco.BI.Extensions
return d;
}
public static string GenerateFaultDescription(this Job j, DiscoDataContext dbContext)
public static string GenerateFaultDescription(this Job j, DiscoDataContext Database)
{
StringBuilder sb = new StringBuilder();
@@ -199,14 +98,14 @@ namespace Disco.BI.Extensions
return sb.ToString();
}
public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext dbContext, PluginFeatureManifest WarrantyProviderDefinition)
public static string GenerateFaultDescriptionFooter(this Job j, DiscoDataContext Database, PluginFeatureManifest WarrantyProviderDefinition)
{
var versionDisco = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
return string.Format("Automation by Disco v{0}.{1}.{2:0000}.{3:0000} (Provider: {4} v{5})",
versionDisco.Major, versionDisco.Minor, versionDisco.Build, versionDisco.Revision, WarrantyProviderDefinition.Id, WarrantyProviderDefinition.PluginManifest.Version.ToString(4));
}
public static void UpdateSubTypes(this Job j, DiscoDataContext dbContext, List<JobSubType> SubTypes, bool AddComponents, User TechUser)
public static void UpdateSubTypes(this Job j, DiscoDataContext Database, List<JobSubType> SubTypes, bool AddComponents, User TechUser)
{
if (SubTypes == null || SubTypes.Count == 0)
throw new ArgumentException("The Job must contain at least one Sub Type");
@@ -246,10 +145,10 @@ namespace Disco.BI.Extensions
foreach (var t in addedSubTypes)
logBuilder.Append("- ").AppendLine(t.ToString());
}
dbContext.JobLogs.Add(new JobLog()
Database.JobLogs.Add(new JobLog()
{
JobId = j.Id,
TechUserId = TechUser.Id,
TechUserId = TechUser.UserId,
Timestamp = DateTime.Now,
Comments = logBuilder.ToString()
});
@@ -258,7 +157,7 @@ namespace Disco.BI.Extensions
// Add Components
if (AddComponents && addedSubTypes.Count > 0 && j.DeviceSerialNumber != null)
{
var components = dbContext.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var addedComponents = new List<DeviceComponent>();
foreach (var c in components)
{
@@ -278,12 +177,12 @@ namespace Disco.BI.Extensions
}
foreach (var c in addedComponents)
{
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.InvariantCultureIgnoreCase)))
if (!j.JobComponents.Any(jc => jc.Description.Equals(c.Description, StringComparison.OrdinalIgnoreCase)))
{ // Job Component with matching Description doesn't exist.
dbContext.JobComponents.Add(new JobComponent()
Database.JobComponents.Add(new JobComponent()
{
Job = j,
TechUserId = TechUser.Id,
TechUserId = TechUser.UserId,
Cost = c.Cost,
Description = c.Description
});
@@ -292,5 +191,42 @@ namespace Disco.BI.Extensions
}
}
private static List<string> FilterCreatableTypePermissions(AuthorizationToken Authorization)
{
if (!Authorization.HasAll(Claims.Job.Types.CreateHMisc, Claims.Job.Types.CreateHNWar, Claims.Job.Types.CreateHWar, Claims.Job.Types.CreateSApp, Claims.Job.Types.CreateSImg, Claims.Job.Types.CreateSOS, Claims.Job.Types.CreateUMgmt))
{
// Must Filter
List<string> allowedTypes = new List<string>(6);
if (Authorization.Has(Claims.Job.Types.CreateHMisc))
allowedTypes.Add(JobType.JobTypeIds.HMisc);
if (Authorization.Has(Claims.Job.Types.CreateHNWar))
allowedTypes.Add(JobType.JobTypeIds.HNWar);
if (Authorization.Has(Claims.Job.Types.CreateHWar))
allowedTypes.Add(JobType.JobTypeIds.HWar);
if (Authorization.Has(Claims.Job.Types.CreateSApp))
allowedTypes.Add(JobType.JobTypeIds.SApp);
if (Authorization.Has(Claims.Job.Types.CreateSImg))
allowedTypes.Add(JobType.JobTypeIds.SImg);
if (Authorization.Has(Claims.Job.Types.CreateSOS))
allowedTypes.Add(JobType.JobTypeIds.SOS);
if (Authorization.Has(Claims.Job.Types.CreateUMgmt))
allowedTypes.Add(JobType.JobTypeIds.UMgmt);
return allowedTypes;
}
return null;
}
public static IQueryable<JobType> FilterCreatableTypePermissions(this IQueryable<JobType> JobTypes, AuthorizationToken Authorization)
{
var allowedTypes = FilterCreatableTypePermissions(Authorization);
if (allowedTypes != null)
{
return JobTypes.Where(jt => allowedTypes.Contains(jt.Id));
}
return JobTypes;
}
}
}
+2 -2
View File
@@ -41,7 +41,7 @@ namespace Disco.BI.Extensions
CacheAllFlags();
var currentFlags = j.Flags ?? 0;
var currentFlags = (long)(j.Flags ?? 0);
foreach (var jt in j.JobSubTypes)
{
@@ -63,7 +63,7 @@ namespace Disco.BI.Extensions
CacheAllFlags();
var currentFlags = j.Flags ?? 0;
var currentFlags = (long)(j.Flags ?? 0);
foreach (var jt in j.JobSubTypes)
{
@@ -0,0 +1,213 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Jobs.JobQueues;
using Disco.Services.Users;
using System;
using System.Linq;
namespace Disco.BI.Extensions
{
public static class JobQueueActionExtensions
{
#region Edit Sla
public static bool CanEditSla(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnySLA))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnSLA))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnEditSla(this JobQueueJob jqj, DateTime? SlaExpiresDate)
{
if (!jqj.CanEditSla())
throw new InvalidOperationException("Editing job SLA for this queue is denied");
if (SlaExpiresDate.HasValue && jqj.AddedDate > SlaExpiresDate.Value)
throw new ArgumentException("The SLA Expires Date must be greater than the Added Date", "SLAExpiresDate");
jqj.SLAExpiresDate = SlaExpiresDate;
}
#endregion
#region Edit Priority
public static bool CanEditPriority(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyPriority))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnPriority))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnEditPriority(this JobQueueJob jqj, JobQueuePriority Priority)
{
if (!jqj.CanEditPriority())
throw new InvalidOperationException("Editing job priority for this queue is denied");
jqj.Priority = Priority;
}
#endregion
#region Edit Comments
private static bool CanEditComments(this JobQueueJob jqj)
{
if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditAnyComments))
{
// Can edit ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Properties.JobQueueProperties.EditOwnComments))
{
// Can edit from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static bool CanEditAddedComment(this JobQueueJob jqj)
{
return jqj.CanEditComments();
}
public static bool CanEditRemovedComment(this JobQueueJob jqj)
{
if (!jqj.RemovedDate.HasValue)
return false;
return jqj.CanEditComments();
}
public static void OnEditAddedComment(this JobQueueJob jqj, string AddedComment)
{
if (!jqj.CanEditAddedComment())
throw new InvalidOperationException("Editing job added comments for this queue is denied");
jqj.AddedComment = string.IsNullOrWhiteSpace(AddedComment) ? null : AddedComment.Trim();
}
public static void OnEditRemovedComment(this JobQueueJob jqj, string RemovedComment)
{
if (!jqj.CanEditRemovedComment())
throw new InvalidOperationException("Editing job removed comments for this queue is denied");
jqj.RemovedComment = string.IsNullOrWhiteSpace(RemovedComment) ? null : RemovedComment.Trim();
}
#endregion
#region Remove
public static bool CanRemove(this JobQueueJob jqj)
{
if (jqj.RemovedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveAnyQueues))
{
// Can remove from ANY queue
return true;
}
else if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.RemoveOwnQueues))
{
// Can remove from OWN queue
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jqj.JobQueueId);
}
else
{
return false;
}
}
public static void OnRemove(this JobQueueJob jqj, User Technician, string Comment)
{
if (!jqj.CanRemove())
throw new InvalidOperationException("Removing job from queue is denied");
jqj.RemovedDate = DateTime.Now;
jqj.RemovedUserId = Technician.UserId;
jqj.RemovedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim();
}
#endregion
#region Add
public static bool CanAddQueues(this Job j)
{
// Job Closed?
if (j.ClosedDate.HasValue)
return false;
if (UserService.CurrentAuthorization.HasAny(Claims.Job.Actions.AddAnyQueues, Claims.Job.Actions.AddOwnQueues))
return true;
return false;
}
public static bool CanAddQueue(this Job j, JobQueue jq)
{
// Shortcut
if (!j.CanAddQueues())
return false;
// Already in Queue?
if (j.JobQueues.Any(jjq => !jjq.RemovedDate.HasValue && jjq.JobQueueId == jq.Id))
return false;
// Can add ANY queue
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddAnyQueues))
return true;
// Can add OWN queue
if (UserService.CurrentAuthorization.Has(Claims.Job.Actions.AddOwnQueues))
{
return JobQueueService.UsersQueues(UserService.CurrentUser).Any(q => q.JobQueue.Id == jq.Id);
}
return false;
}
public static JobQueueJob OnAddQueue(this Job j, DiscoDataContext Database, JobQueue jq, User Technician, string Comment, DateTime? SLAExpires, JobQueuePriority Priority)
{
if (!j.CanAddQueue(jq))
throw new InvalidOperationException("Adding job to queue is denied");
if (SLAExpires.HasValue && SLAExpires.Value < DateTime.Now)
throw new ArgumentException("The SLA Date must be greater than the current time", "SLAExpires");
var jqj = new JobQueueJob()
{
JobQueueId = jq.Id,
JobId = j.Id,
AddedDate = DateTime.Now,
AddedUserId = Technician.UserId,
AddedComment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(),
SLAExpiresDate = SLAExpires,
Priority = Priority
};
Database.JobQueueJobs.Add(jqj);
return jqj;
}
#endregion
}
}
@@ -1,103 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Job;
using Disco.Models.Repository;
using Disco.Data.Repository;
namespace Disco.BI.Extensions
{
public static class JobTableExtensions
{
public static List<JobTableModel.JobTableItemModel> DetermineItems(this JobTableModel model, DiscoDataContext dbContext, IQueryable<Job> Jobs)
{
List<JobTableModel.JobTableItemModel> items;
if (model.ShowStatus)
{
var jobItems = Jobs.Select(j => new JobTableModel.JobTableItemModelIncludeStatus()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
DeviceSerialNumber = j.Device.SerialNumber,
DeviceProfileId = j.Device.DeviceProfileId,
DeviceModelId = j.Device.DeviceModelId,
DeviceModelDescription = j.Device.DeviceModel.Description,
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
UserId = j.UserId,
UserDisplayName = j.User.DisplayName,
OpenedTechUserId = j.OpenedTechUserId,
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
Location = j.DeviceHeldLocation,
JobMetaWarranty_ExternalReference = j.JobMetaWarranty.ExternalReference,
JobMetaWarranty_ExternalCompletedDate = j.JobMetaWarranty.ExternalCompletedDate,
JobMetaNonWarranty_RepairerLoggedDate = j.JobMetaNonWarranty.RepairerLoggedDate,
JobMetaNonWarranty_RepairerCompletedDate = j.JobMetaNonWarranty.RepairerCompletedDate,
JobMetaNonWarranty_AccountingChargeAddedDate = j.JobMetaNonWarranty.AccountingChargeAddedDate,
JobMetaNonWarranty_AccountingChargePaidDate = j.JobMetaNonWarranty.AccountingChargePaidDate,
JobMetaNonWarranty_AccountingChargeRequiredDate = j.JobMetaNonWarranty.AccountingChargeRequiredDate,
JobMetaNonWarranty_IsInsuranceClaim = j.JobMetaNonWarranty.IsInsuranceClaim,
JobMetaInsurance_ClaimFormSentDate = j.JobMetaInsurance.ClaimFormSentDate,
WaitingForUserAction = j.WaitingForUserAction,
DeviceReadyForReturn = j.DeviceReadyForReturn,
DeviceHeld = j.DeviceHeld,
DeviceReturnedDate = j.DeviceReturnedDate,
JobMetaWarranty_ExternalName = j.JobMetaWarranty.ExternalName,
JobMetaNonWarranty_RepairerName = j.JobMetaNonWarranty.RepairerName
});
items = new List<JobTableModel.JobTableItemModel>();
foreach (var j in jobItems)
{
j.StatusId = j.CalculateStatusId();
j.StatusDescription = JobBI.Utilities.JobStatusDescription(j.StatusId, j);
items.Add(j);
}
}
else
{
items = Jobs.Select(j => new JobTableModel.JobTableItemModel()
{
Id = j.Id,
OpenedDate = j.OpenedDate,
ClosedDate = j.ClosedDate,
TypeId = j.JobTypeId,
TypeDescription = j.JobType.Description,
DeviceSerialNumber = j.Device.SerialNumber,
DeviceProfileId = j.Device.DeviceProfileId,
DeviceModelId = j.Device.DeviceModelId,
DeviceModelDescription = j.Device.DeviceModel.Description,
DeviceAddressId = j.Device.DeviceProfile.DefaultOrganisationAddress,
UserId = j.UserId,
UserDisplayName = j.User.DisplayName,
OpenedTechUserId = j.OpenedTechUserId,
OpenedTechUserDisplayName = j.OpenedTechUser.DisplayName,
Location = j.DeviceHeldLocation
}).ToList();
}
if (!model.ShowDeviceAddress.HasValue)
model.ShowDeviceAddress = dbContext.DiscoConfiguration.MultiSiteMode;
foreach (var j in items)
if (j.DeviceAddressId.HasValue)
j.DeviceAddress = dbContext.DiscoConfiguration.OrganisationAddresses.GetAddress(j.DeviceAddressId.Value).Name;
return items;
}
public static void Fill(this JobTableModel model, DiscoDataContext dbContext, IQueryable<Job> Jobs)
{
model.Items = model.DetermineItems(dbContext, Jobs);
}
}
}
+23 -15
View File
@@ -6,21 +6,21 @@ using Disco.Models.Repository;
using Disco.Data.Repository;
using System.IO;
using Disco.Models.BI.DocumentTemplates;
using Disco.Models.Interop.ActiveDirectory;
using Disco.Services.Interop.ActiveDirectory;
namespace Disco.BI.Extensions
{
public static class UserExtensions
{
public static UserAttachment CreateAttachment(this User User, DiscoDataContext dbContext, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
public static UserAttachment CreateAttachment(this User User, DiscoDataContext Database, User CreatorUser, string Filename, string MimeType, string Comments, Stream Content, DocumentTemplate DocumentTemplate = null, byte[] PdfThumbnail = null)
{
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.InvariantCultureIgnoreCase))
if (string.IsNullOrEmpty(MimeType) || MimeType.Equals("unknown/unknown", StringComparison.OrdinalIgnoreCase))
MimeType = Interop.MimeTypes.ResolveMimeType(Filename);
UserAttachment ua = new UserAttachment()
{
UserId = User.Id,
TechUserId = CreatorUser.Id,
UserId = User.UserId,
TechUserId = CreatorUser.UserId,
Filename = Filename,
MimeType = MimeType,
Timestamp = DateTime.Now,
@@ -30,25 +30,25 @@ namespace Disco.BI.Extensions
if (DocumentTemplate != null)
ua.DocumentTemplateId = DocumentTemplate.Id;
dbContext.UserAttachments.Add(ua);
dbContext.SaveChanges();
Database.UserAttachments.Add(ua);
Database.SaveChanges();
ua.SaveAttachment(dbContext, Content);
ua.SaveAttachment(Database, Content);
Content.Position = 0;
if (PdfThumbnail == null)
ua.GenerateThumbnail(dbContext, Content);
ua.GenerateThumbnail(Database, Content);
else
ua.SaveThumbnailAttachment(dbContext, PdfThumbnail);
ua.SaveThumbnailAttachment(Database, PdfThumbnail);
return ua;
}
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext dbContext, User User, DateTime TimeStamp)
public static List<DocumentTemplate> AvailableDocumentTemplates(this User u, DiscoDataContext Database, User User, DateTime TimeStamp)
{
var dts = dbContext.DocumentTemplates.Include("JobSubTypes")
var dts = Database.DocumentTemplates.Include("JobSubTypes")
.Where(dt => dt.Scope == DocumentTemplate.DocumentTemplateScopes.User)
.ToArray()
.Where(dt => dt.FilterExpressionMatches(u, dbContext, User, TimeStamp, DocumentState.DefaultState())).ToList();
.Where(dt => dt.FilterExpressionMatches(u, Database, User, TimeStamp, DocumentState.DefaultState())).ToList();
return dts;
}
@@ -57,9 +57,17 @@ namespace Disco.BI.Extensions
{
return u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).ToList();
}
public static ActiveDirectoryUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
public static ADUserAccount ActiveDirectoryAccount(this User User, params string[] AdditionalProperties)
{
return Interop.ActiveDirectory.ActiveDirectory.GetUserAccount(User.Id, AdditionalProperties);
return ActiveDirectory.RetrieveADUserAccount(User.UserId, AdditionalProperties);
}
public static bool CanCreateJob(this User u)
{
if (!JobActionExtensions.CanCreate())
return false;
return true;
}
}
}
@@ -0,0 +1,85 @@
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Extensions
{
public static class UserFlagActionExtensions
{
#region Edit Comments
public static bool CanEditComments(this UserFlagAssignment fa)
{
return UserService.CurrentAuthorization.Has(Claims.User.Actions.EditFlags);
}
public static void OnEditComments(this UserFlagAssignment fa, string Comments)
{
if (!fa.CanEditComments())
throw new InvalidOperationException("Editing comments for user flags is denied");
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim();
}
#endregion
#region Remove
public static bool CanRemove(this UserFlagAssignment fa)
{
if (fa.RemovedDate.HasValue)
return false;
return UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveFlags);
}
public static void OnRemove(this UserFlagAssignment fa, User Technician)
{
if (!fa.CanRemove())
throw new InvalidOperationException("Removing user flags is denied");
fa.RemovedDate = DateTime.Now;
fa.RemovedUserId = Technician.UserId;
}
#endregion
#region Add
public static bool CanAddUserFlags(this User u)
{
return UserService.CurrentAuthorization.Has(Claims.User.Actions.AddFlags);
}
public static bool CanAddUserFlag(this User u, UserFlag flag)
{
// Shortcut
if (!u.CanAddUserFlags())
return false;
// Already has User Flag?
if (u.UserFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.UserFlagId == flag.Id))
return false;
return true;
}
public static UserFlagAssignment OnAddUserFlag(this User u, DiscoDataContext Database, UserFlag flag, User Technician, string Comments)
{
if (!u.CanAddUserFlag(flag))
throw new InvalidOperationException("Adding user flag is denied");
var fa = new UserFlagAssignment()
{
UserFlagId = flag.Id,
UserId = u.UserId,
AddedDate = DateTime.Now,
AddedUserId = Technician.UserId,
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim()
};
Database.UserFlagAssignments.Add(fa);
return fa;
}
#endregion
}
}
+1 -112
View File
@@ -23,117 +23,6 @@ namespace Disco.BI.Extensions
}
}
#region Date/Time Extensions
public static string ToFuzzy(this DateTime d)
{
var n = DateTime.Now;
// Today
if (d.Date == n.Date)
{
if (d < n)
{
// Earlier
if (d > n.AddMinutes(-1))
return "A moment ago";
if (d > n.AddMinutes(-10))
return "A few minutes ago";
}
else
{
// Later
if (d < n.AddMinutes(1))
return "In a moment";
if (d < n.AddMinutes(10))
return "In a few minutes";
}
return string.Format("Today at {0:h:mm tt}", d);
}
if (d.Date < n.Date)
{
// PAST
var dif = n.Subtract(d);
// Yesterday
if (d.Date == n.Date.AddDays(-1))
return string.Format("Yesterday at {0:h:mm tt}", d);
// Last Week
if (dif.TotalDays <= 7)
return string.Format("Last {0:dddd} at {0:h:mm tt}", d);
// Within 8 Weeks
if (d > n.Date.AddMonths(-2))
return string.Format("{0} Weeks ago, {1:ddd, d MMM}", (int)(dif.TotalDays / 7), d);
// Same Year
if (d.Year == n.Year)
return string.Format("{0} Months ago, {1:ddd, d MMM}", (int)(dif.TotalDays / 30), d);
}
else
{
// Future
var dif = d.Subtract(n);
// Tomorrow
if (d.Date == n.Date.AddDays(1))
return string.Format("Tomorrow at {0:h:mm tt}", d);
// Next Week
if (dif.TotalDays <= 7)
return string.Format("Next {0:dddd} at {0:h:mm tt}", d);
// < 2 Month
if (d < n.Date.AddMonths(2))
return string.Format("In {0} Weeks, {1:ddd, d MMM}", (int)(dif.TotalDays / 7), d);
// Same Year
if (d.Year == n.Year)
return string.Format("In {0} Months, {1:ddd, d MMM}", (int)(dif.TotalDays / 30), d);
}
return d.ToString("ddd, d MMM yyyy");
}
public static string ToFuzzy(this DateTime? d, string NullValue = "N/A")
{
if (d.HasValue)
return ToFuzzy(d.Value);
else
return NullValue;
}
public static string ToFullDateTime(this DateTime d)
{
return d.ToString("ddd, d MMM yyyy @ h:mm:sstt");
}
public static string ToFullDateTime(this DateTime? d, string NullValue = "N/A")
{
if (d.HasValue)
return ToFullDateTime(d.Value);
else
return NullValue;
}
public static long ToSortableDateTime(this DateTime? d)
{
if (d.HasValue)
return d.Value.ToBinary();
else
return -1;
}
public static long ToSortableDateTime(this DateTime d)
{
return d.ToBinary();
}
public static string ToJavascriptDateTime(this DateTime d)
{
return d.ToString("yyyy/MM/dd hh:mm tt");
}
public static string ToJavascriptDateTime(this DateTime? d)
{
if (d.HasValue)
return d.Value.ToString("yyyy/MM/dd hh:mm tt");
else
return null;
}
#endregion
#region Image Extensions
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
@@ -277,7 +166,7 @@ namespace Disco.BI.Extensions
}
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
{
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (jpgCodec != null)
{
if (Quality < 0 || Quality > 100)
@@ -1,397 +0,0 @@
using Disco.Models.Interop.ActiveDirectory;
using Disco.BI.DeviceBI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices;
using System.Linq;
using System.IO;
namespace Disco.BI.Interop.ActiveDirectory
{
public static class ActiveDirectory
{
public static ActiveDirectoryMachineAccount GetMachineAccount(string ComputerName, System.Guid? UUIDNetbootGUID = null, System.Guid? MacAddressNetbootGUID = null, params string[] AdditionalProperties)
{
if (string.IsNullOrWhiteSpace(ComputerName))
throw new System.ArgumentException("Invalid Computer Name - Empty", "ComputerName");
if (ComputerName.Contains("\\"))
ComputerName = ComputerName.Substring(checked(ComputerName.IndexOf("\\") + 1));
if (ComputerName.Length > 24)
throw new System.ArgumentException("Invalid Computer Name - Length > 24", "ComputerName");
string sAMAccountName = ComputerName;
if (!sAMAccountName.EndsWith("$"))
sAMAccountName = string.Format("{0}$", sAMAccountName);
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
{
var loadProperties = new List<string> { "name", "distinguishedName", "sAMAccountName", "objectSid", "dNSHostName", "netbootGUID", "isCriticalSystemObject" };
loadProperties.AddRange(AdditionalProperties);
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectClass=computer)(sAMAccountName={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), loadProperties.ToArray(), SearchScope.Subtree))
{
SearchResult dResult = dSearcher.FindOne();
if (dResult != null)
{
return ActiveDirectory.DirectorySearchResultToMachineAccount(dResult, AdditionalProperties);
}
}
if (UUIDNetbootGUID.HasValue)
{
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectClass=computer)(netbootGUID={0}))", ActiveDirectoryHelpers.FormatGuidForLdapQuery(UUIDNetbootGUID.Value)), loadProperties.ToArray(), SearchScope.Subtree))
{
SearchResult dResult = dSearcher.FindOne();
if (dResult != null)
{
return ActiveDirectory.DirectorySearchResultToMachineAccount(dResult, AdditionalProperties);
}
}
}
if (MacAddressNetbootGUID.HasValue)
{
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectClass=computer)(netbootGUID={0}))", ActiveDirectoryHelpers.FormatGuidForLdapQuery(MacAddressNetbootGUID.Value)), loadProperties.ToArray(), SearchScope.Subtree))
{
SearchResult dResult = dSearcher.FindOne();
if (dResult != null)
{
return ActiveDirectory.DirectorySearchResultToMachineAccount(dResult, AdditionalProperties);
}
}
}
}
return null;
}
private static ActiveDirectoryMachineAccount DirectorySearchResultToMachineAccount(SearchResult result, params string[] AdditionalProperties)
{
string name = result.Properties["name"][0].ToString();
string sAMAccountName = result.Properties["sAMAccountName"][0].ToString();
string distinguishedName = result.Properties["distinguishedName"][0].ToString();
string objectSid = ActiveDirectoryHelpers.ConvertBytesToSIDString((byte[])result.Properties["objectSid"][0]);
var dNSNameProperty = result.Properties["dNSHostName"];
string dNSName = null;
if (dNSNameProperty.Count > 0)
dNSName = dNSNameProperty[0].ToString();
else
dNSName = string.Format("{0}.{1}", sAMAccountName.TrimEnd('$'), ActiveDirectoryHelpers.DefaultDomainQualifiedName);
bool isCriticalSystemObject = (bool)result.Properties["isCriticalSystemObject"][0];
System.Guid netbootGUIDResult = default(System.Guid);
ResultPropertyValueCollection netbootGUIDProp = result.Properties["netbootGUID"];
if (netbootGUIDProp.Count > 0)
{
netbootGUIDResult = new System.Guid((byte[])netbootGUIDProp[0]);
}
// Additional Properties
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
foreach (string propertyName in AdditionalProperties)
{
var property = result.Properties[propertyName];
var propertyValues = new List<object>();
for (int index = 0; index < property.Count; index++)
propertyValues.Add(property[index]);
additionalProperties.Add(propertyName, propertyValues.ToArray());
}
return new ActiveDirectoryMachineAccount
{
Name = name,
DistinguishedName = distinguishedName,
sAMAccountName = sAMAccountName,
ObjectSid = objectSid,
NetbootGUID = netbootGUIDResult,
Path = result.Path,
Domain = ActiveDirectoryHelpers.DefaultDomainNetBiosName,
DnsName = dNSName,
IsCriticalSystemObject = isCriticalSystemObject,
LoadedProperties = additionalProperties
};
}
private static ActiveDirectoryUserAccount SearchResultToActiveDirectoryUserAccount(SearchResult result, params string[] AdditionalProperties)
{
string name = result.Properties["name"][0].ToString();
string username = result.Properties["sAMAccountName"][0].ToString();
string distinguishedName = result.Properties["distinguishedName"][0].ToString();
string objectSid = ActiveDirectoryHelpers.ConvertBytesToSIDString((byte[])result.Properties["objectSid"][0]);
ResultPropertyValueCollection displayNameProp = result.Properties["displayName"];
string displayName = username;
if (displayNameProp.Count > 0)
displayName = displayNameProp[0].ToString();
string surname = null;
ResultPropertyValueCollection surnameProp = result.Properties["sn"];
if (surnameProp.Count > 0)
surname = surnameProp[0].ToString();
string givenName = null;
ResultPropertyValueCollection givenNameProp = result.Properties["givenName"];
if (givenNameProp.Count > 0)
givenName = givenNameProp[0].ToString();
string email = null;
ResultPropertyValueCollection emailProp = result.Properties["mail"];
if (emailProp.Count > 0)
email = emailProp[0].ToString();
string phone = null;
ResultPropertyValueCollection phoneProp = result.Properties["telephoneNumber"];
if (phoneProp.Count > 0)
phone = phoneProp[0].ToString();
IEnumerable<string> groupCNs = result.Properties["memberOf"].Cast<string>();
List<string> groups = ActiveDirectoryCachedGroups.GetGroups(groupCNs).Select(g => g.ToLower()).ToList();
//foreach (string groupCN in result.Properties["memberOf"])
//{
// Removed 2012-11-30 G# - Moved to Recursive Cache
//var groupCNlower = groupCN.ToLower();
//if (groupCNlower.StartsWith("cn="))
// groups.Add(groupCNlower.Substring(3, groupCNlower.IndexOf(",") - 3));
// End Removed 2012-11-30 G#
//}
string type = null;
if (groups.Contains("domain admins") || groups.Contains("disco admins"))
{
type = "Admin";
}
else
{
if (groups.Contains("staff"))
{
type = "Staff";
}
else
{
if (groups.Contains("students"))
{
type = "Student";
}
}
}
// Additional Properties
Dictionary<string, object[]> additionalProperties = new Dictionary<string, object[]>();
foreach (string propertyName in AdditionalProperties)
{
var property = result.Properties[propertyName];
var propertyValues = new List<object>();
for (int index = 0; index < property.Count; index++)
propertyValues.Add(property[index]);
additionalProperties.Add(propertyName, propertyValues.ToArray());
}
return new ActiveDirectoryUserAccount
{
Domain = ActiveDirectoryHelpers.DefaultDomainNetBiosName,
Name = name,
Surname = surname,
GivenName = givenName,
Email = email,
Phone = phone,
DistinguishedName = distinguishedName,
sAMAccountName = username,
DisplayName = displayName,
ObjectSid = objectSid,
Type = type,
Path = result.Path,
LoadedProperties = additionalProperties
};
}
public static ActiveDirectoryUserAccount GetUserAccount(string Username, params string[] AdditionalProperties)
{
if (string.IsNullOrWhiteSpace(Username))
throw new System.ArgumentException("Invalid User Account", "Username");
string sAMAccountName = Username;
if (sAMAccountName.Contains("\\"))
sAMAccountName = sAMAccountName.Substring(checked(sAMAccountName.IndexOf("\\") + 1));
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultLdapRoot)
{
var loadProperties = new List<string> {
"name",
"distinguishedName",
"sAMAccountName",
"objectSid",
"displayName",
"sn",
"givenName",
"memberOf",
"mail",
"telephoneNumber"
};
loadProperties.AddRange(AdditionalProperties);
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectClass=user)(sAMAccountName={0}))", ActiveDirectoryHelpers.EscapeLdapQuery(sAMAccountName)), loadProperties.ToArray(), SearchScope.Subtree))
{
SearchResult dResult = dSearcher.FindOne();
if (dResult != null)
return ActiveDirectory.SearchResultToActiveDirectoryUserAccount(dResult, AdditionalProperties);
else
return null;
}
}
}
public static string OfflineDomainJoinProvision(ref ActiveDirectoryMachineAccount ExistingAccount, string ComputerName, string OrganisationalUnit = null, string EnrolSessionId = null)
{
if (ExistingAccount != null && ExistingAccount.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", ExistingAccount.DistinguishedName));
string DJoinResult = null;
if (string.IsNullOrWhiteSpace(ComputerName) || ComputerName.Length > 24)
throw new System.ArgumentException("Invalid Computer Name; > 0 and <= 24", "ComputerName");
// Added 2012-10-25 G#
// Ensure Specified OU Exists
if (!string.IsNullOrEmpty(OrganisationalUnit))
{
var ouPath = string.Format("{0}{1},{2}", ActiveDirectoryHelpers.DefaultLdapPath, OrganisationalUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
try
{
using (DirectoryEntry ou = new DirectoryEntry(ouPath))
{
if (ou == null)
{
throw new Exception("OU's Directory Entry couldn't be found");
}
}
}
catch (Exception ex)
{
throw new ArgumentException(string.Format("An error occurred while trying to locate the specified OU: {0}", ouPath), "OrganisationalUnit", ex);
}
}
// End Added 2012-10-25 G#
// Delete Existing
if (ExistingAccount != null)
ExistingAccount.DeleteAccount();
string tempFileName = System.IO.Path.GetTempFileName();
string argumentOU = (!string.IsNullOrWhiteSpace(OrganisationalUnit)) ? string.Format(" /MACHINEOU \"{0},{1}\"", OrganisationalUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName) : string.Empty;
string arguments = string.Format("/PROVISION /DOMAIN \"{0}\" /DCNAME \"{1}\" /MACHINE \"{2}\"{3} /REUSE /SAVEFILE \"{4}\"",
ActiveDirectoryHelpers.DefaultDomainName,
ActiveDirectoryHelpers.DefaultDomainPDCName,
ComputerName,
argumentOU,
tempFileName
);
ProcessStartInfo commandStarter = new ProcessStartInfo("DJOIN.EXE", arguments)
{
CreateNoWindow = true,
ErrorDialog = false,
LoadUserProfile = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
if (EnrolSessionId != null)
{
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, string.Format("{0} {1}{2}", "DJOIN.EXE", arguments, System.Environment.NewLine));
}
string stdOutput;
string stdError;
using (Process commandProc = Process.Start(commandStarter))
{
commandProc.WaitForExit(20000);
stdOutput = commandProc.StandardOutput.ReadToEnd();
stdError = commandProc.StandardError.ReadToEnd();
}
if (EnrolSessionId != null)
{
if (!string.IsNullOrWhiteSpace(stdOutput))
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, stdOutput + System.Environment.NewLine);
if (!string.IsNullOrWhiteSpace(stdError))
EnrolmentLog.LogSessionDiagnosticInformation(EnrolSessionId, stdError + System.Environment.NewLine);
}
if (System.IO.File.Exists(tempFileName))
{
DJoinResult = System.Convert.ToBase64String(System.IO.File.ReadAllBytes(tempFileName));
System.IO.File.Delete(tempFileName);
}
if (string.IsNullOrWhiteSpace(DJoinResult))
throw new System.InvalidOperationException(string.Format("Domain Join Unsuccessful{0}Error: {1}{0}Output: {2}", System.Environment.NewLine, stdError, stdOutput));
ExistingAccount = ActiveDirectory.GetMachineAccount(ComputerName);
return DJoinResult;
}
public static List<ActiveDirectoryUserAccount> SearchUsers(string term)
{
List<ActiveDirectoryUserAccount> users = new List<ActiveDirectoryUserAccount>();
string defaultQualifiedDomainName = ActiveDirectoryHelpers.DefaultDomainQualifiedName;
string defaultNetBiosDomainName = ActiveDirectoryHelpers.DefaultDomainNetBiosName;
term = ActiveDirectoryHelpers.EscapeLdapQuery(term);
using (DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", defaultQualifiedDomainName)))
{
using (DirectorySearcher searcher = new DirectorySearcher(entry, string.Format("(&(objectClass=User)(objectCategory=Person)(|(sAMAccountName=*{0}*)(displayName=*{0}*)))", term), new string[]
{
"name",
"distinguishedName",
"sAMAccountName",
"objectSid",
"displayName",
"sn",
"givenName",
"memberOf",
"mail",
"telephoneNumber"
}, SearchScope.Subtree))
{
searcher.SizeLimit = 30;
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult result in results)
{
users.Add(ActiveDirectory.SearchResultToActiveDirectoryUserAccount(result));
}
}
}
return users;
}
public static List<ActiveDirectoryOrganisationalUnit> GetOrganisationalUnitStructure()
{
ActiveDirectoryOrganisationalUnit DomainOUs = new ActiveDirectoryOrganisationalUnit
{
Children = new System.Collections.Generic.List<ActiveDirectoryOrganisationalUnit>()
};
string defaultQualifiedDomainName = ActiveDirectoryHelpers.DefaultDomainQualifiedName;
using (DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", defaultQualifiedDomainName)))
{
ActiveDirectory.GetOrganisationalUnitStructure_Recursive(ref DomainOUs, entry);
}
return DomainOUs.Children;
}
private static void GetOrganisationalUnitStructure_Recursive(ref ActiveDirectoryOrganisationalUnit ParentOU, DirectoryEntry Container)
{
using (DirectorySearcher searcher = new DirectorySearcher(Container, "(objectCategory=organizationalUnit)", new string[]
{
"name",
"distinguishedName"
}, SearchScope.OneLevel))
{
using (SearchResultCollection results = searcher.FindAll())
{
foreach (SearchResult result in results)
{
string i = result.Properties["name"][0].ToString();
string dn = result.Properties["distinguishedName"][0].ToString();
ActiveDirectoryOrganisationalUnit ChildOU = new ActiveDirectoryOrganisationalUnit
{
Name = i,
Path = dn.Substring(0, dn.IndexOf(",DC=")),
Children = new List<ActiveDirectoryOrganisationalUnit>()
};
ActiveDirectory.GetOrganisationalUnitStructure_Recursive(ref ChildOU, result.GetDirectoryEntry());
if (ChildOU.Children.Count == 0)
ChildOU.Children = null;
ParentOU.Children.Add(ChildOU);
}
}
}
}
}
}
@@ -1,186 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
namespace Disco.BI.Interop.ActiveDirectory
{
public class ActiveDirectoryCachedGroups : ScheduledTask
{
private static ConcurrentDictionary<string, Tuple<ADCachedGroup, DateTime>> _Cache = new ConcurrentDictionary<string, Tuple<ADCachedGroup, DateTime>>();
private const long CacheTimeoutTicks = 6000000000; // 10 Minutes
public static IEnumerable<string> GetGroups(IEnumerable<string> GroupCNs)
{
List<ADCachedGroup> groups = new List<ADCachedGroup>();
foreach (var groupCN in GroupCNs)
foreach (var group in GetGroupsRecursive(groupCN, new Stack<ADCachedGroup>()))
if (!groups.Contains(group))
{
groups.Add(group);
yield return group.FriendlyName;
}
}
public static IEnumerable<string> GetGroups(string GroupCN)
{
foreach (var group in GetGroupsRecursive(GroupCN, new Stack<ADCachedGroup>()))
yield return group.FriendlyName;
}
private static IEnumerable<ADCachedGroup> GetGroupsRecursive(string GroupCN, Stack<ADCachedGroup> RecursiveTree)
{
var group = GetGroup(GroupCN);
if (group != null && !RecursiveTree.Contains(group))
{
yield return group;
if (group.MemberOf != null)
{
RecursiveTree.Push(group);
foreach (var memberOfGroupCN in group.MemberOf)
foreach (var memberOfGroup in GetGroupsRecursive(memberOfGroupCN, RecursiveTree))
yield return memberOfGroup;
RecursiveTree.Pop();
}
}
}
private static ADCachedGroup GetGroup(string GroupCN)
{
// Check Cache
Tuple<ADCachedGroup, DateTime> groupRecord = TryCache(GroupCN);
if (groupRecord == null)
{
// Load from AD
var group = ADCachedGroup.LoadFromAD(GroupCN);
SetValue(GroupCN, group);
return group;
}
else
{
// Return from Cache
return groupRecord.Item1;
}
}
private static Tuple<ADCachedGroup, DateTime> TryCache(string GroupCN)
{
string groupCN = GroupCN.ToLower();
Tuple<ADCachedGroup, DateTime> groupRecord;
if (_Cache.TryGetValue(groupCN, out groupRecord))
{
if (groupRecord.Item2 > DateTime.Now)
return groupRecord;
else
_Cache.TryRemove(groupCN, out groupRecord);
}
return null;
}
private static bool SetValue(string GroupCN, ADCachedGroup GroupRecord)
{
string key = GroupCN.ToLower();
Tuple<ADCachedGroup, DateTime> groupRecord = new Tuple<ADCachedGroup, DateTime>(GroupRecord, DateTime.Now.AddTicks(CacheTimeoutTicks));
if (_Cache.ContainsKey(key))
{
Tuple<ADCachedGroup, DateTime> oldGroupRecord;
if (_Cache.TryGetValue(key, out oldGroupRecord))
{
return _Cache.TryUpdate(key, groupRecord, oldGroupRecord);
}
}
return _Cache.TryAdd(key, groupRecord);
}
private class ADCachedGroup
{
public string CN { get; private set; }
public string FriendlyName { get; private set; }
public List<string> MemberOf { get; private set; }
public static ADCachedGroup LoadFromAD(string CN)
{
ADCachedGroup group = null;
using (DirectoryEntry groupDE = new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, CN)))
{
if (groupDE != null)
{
group = new ADCachedGroup()
{
CN = CN
};
group.FriendlyName = (string)groupDE.Properties["sAMAccountName"].Value;
var groupMemberOf = groupDE.Properties["memberOf"];
if (groupMemberOf != null && groupMemberOf.Count > 0)
{
group.MemberOf = groupMemberOf.Cast<string>().ToList();
}
}
}
return group;
}
private ADCachedGroup()
{
// Private Constructor
}
}
private static void CleanStaleCache()
{
var groupKeys = _Cache.Keys.ToArray();
foreach (string groupKey in groupKeys)
{
Tuple<ADCachedGroup, DateTime> groupRecord;
if (_Cache.TryGetValue(groupKey, out groupRecord))
{
if (groupRecord.Item2 <= DateTime.Now)
_Cache.TryRemove(groupKey, out groupRecord);
}
}
}
public override string TaskName { get { return "AD Group Cache - Clean Stale Cache"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
{
// Run @ every 15mins
// Next 15min interval
DateTime now = DateTime.Now;
int mins = (15 - (now.Minute % 15));
if (mins < 10)
mins += 15;
DateTimeOffset startAt = new DateTimeOffset(now).AddMinutes(mins).AddSeconds(now.Second * -1).AddMilliseconds(now.Millisecond * -1);
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(startAt).
WithSchedule(SimpleScheduleBuilder.RepeatMinutelyForever(15));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
CleanStaleCache();
}
}
}
@@ -1,169 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace Disco.BI.Interop.ActiveDirectory
{
internal static class ActiveDirectoryHelpers
{
#region Static Cached Properties
private static string _DefaultDomainName;
private static string _DefaultDomainPDCName;
private static System.Collections.Generic.List<string> _DefaultDomainDCNames;
private static string _DefaultDomainNetBiosName;
private static string _DefaultDomainQualifiedName;
private static string _DefaultLdapPath;
private static bool _DetermineDomainProperties_Loaded = false;
private static object _DetermineDomainProperties_Lock = new object();
internal static string DefaultDomainName
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultDomainName;
}
}
internal static string DefaultDomainPDCName
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultDomainPDCName;
}
}
internal static System.Collections.Generic.List<string> DefaultDomainDCNames
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultDomainDCNames;
}
}
internal static string DefaultDomainNetBiosName
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultDomainNetBiosName;
}
}
internal static string DefaultDomainQualifiedName
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultDomainQualifiedName;
}
}
internal static string DefaultLdapPath
{
get
{
ActiveDirectoryHelpers.DetermineDomainProperties();
return ActiveDirectoryHelpers._DefaultLdapPath;
}
}
internal static string DefaultDCLdapPath(string DC)
{
return string.Format("LDAP://{0}/", DC);
}
internal static DirectoryEntry DefaultLdapRoot
{
get
{
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName));
}
}
internal static DirectoryEntry DefaultDCLdapRoot(string DC)
{
return new DirectoryEntry(string.Concat(ActiveDirectoryHelpers.DefaultDCLdapPath(DC), ActiveDirectoryHelpers.DefaultDomainQualifiedName));
}
private static void DetermineDomainProperties()
{
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
{
lock (ActiveDirectoryHelpers._DetermineDomainProperties_Lock)
{
if (!ActiveDirectoryHelpers._DetermineDomainProperties_Loaded)
{
using (Domain domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain)))
{
ActiveDirectoryHelpers._DefaultDomainName = domain.Name;
ActiveDirectoryHelpers._DefaultDomainPDCName = domain.PdcRoleOwner.Name;
ActiveDirectoryHelpers._DefaultDomainDCNames = new System.Collections.Generic.List<string>(domain.DomainControllers.Count);
foreach (DomainController dc in domain.DomainControllers)
{
ActiveDirectoryHelpers._DefaultDomainDCNames.Add(dc.Name);
}
}
ActiveDirectoryHelpers._DefaultDomainQualifiedName = string.Format("DC={0}", ActiveDirectoryHelpers._DefaultDomainName.Replace(".", ",DC="));
ActiveDirectoryHelpers._DefaultLdapPath = string.Format("LDAP://{0}/", ActiveDirectoryHelpers._DefaultDomainPDCName);
using (DirectoryEntry entry = new DirectoryEntry(string.Format("{0}CN=Partitions,CN=Configuration,{1}", ActiveDirectoryHelpers._DefaultLdapPath, ActiveDirectoryHelpers._DefaultDomainQualifiedName)))
{
using (DirectorySearcher searcher = new DirectorySearcher(entry, "(&(objectClass=crossRef)(nETBIOSName=*))", new string[] { "nETBIOSName" }))
{
SearchResult result = searcher.FindOne();
if (result != null)
{
ActiveDirectoryHelpers._DefaultDomainNetBiosName = result.Properties["nETBIOSName"][0].ToString();
}
else
{
ActiveDirectoryHelpers._DefaultDomainNetBiosName = ActiveDirectoryHelpers._DefaultDomainQualifiedName;
}
}
}
}
ActiveDirectoryHelpers._DetermineDomainProperties_Loaded = true;
}
}
}
#endregion
[System.Runtime.InteropServices.DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool ConvertSidToStringSid(byte[] pSID, ref System.Text.StringBuilder ptrSid);
internal static string ConvertBytesToSIDString(byte[] SID)
{
System.Text.StringBuilder sidString = new System.Text.StringBuilder();
bool flag = ActiveDirectoryHelpers.ConvertSidToStringSid(SID, ref sidString);
string ConvertBytesToSIDString;
if (flag)
{
ConvertBytesToSIDString = sidString.ToString();
}
else
{
ConvertBytesToSIDString = null;
}
return ConvertBytesToSIDString;
}
internal static string EscapeLdapQuery(string query)
{
return query.Replace("*", "\\2a").Replace("(", "\\28").Replace(")", "\\29").Replace("\\", "\\5c").Replace("NUL", "\\00").Replace("/", "\\2f");
}
internal static string FormatGuidForLdapQuery(System.Guid g)
{
checked
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
byte[] array = g.ToByteArray();
for (int i = 0; i < array.Length; i++)
{
byte b = array[i];
sb.Append("\\");
sb.Append(b.ToString("X2"));
}
return sb.ToString();
}
}
}
}
@@ -1,290 +0,0 @@
using Disco.Models.Interop.ActiveDirectory;
using Disco.Models.Repository;
using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Text;
using System.Net.NetworkInformation;
using System.Management;
namespace Disco.BI.Interop.ActiveDirectory
{
public static class ActiveDirectoryMachineAccountExtensions
{
public static void DeleteAccount(this ActiveDirectoryMachineAccount account)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
{
DeleteAccountRecursive(machineDE);
using (var machineDEParent = machineDE.Parent)
{
machineDEParent.Children.Remove(machineDE);
}
}
}
private static void DeleteAccountRecursive(DirectoryEntry parent)
{
List<DirectoryEntry> children = new List<DirectoryEntry>();
foreach (DirectoryEntry child in parent.Children)
children.Add(child);
foreach (var child in children)
{
DeleteAccountRecursive(child);
parent.Children.Remove(child);
child.Dispose();
}
}
private static void SetNetbootGUID(this ActiveDirectoryMachineAccount account, System.Guid updatedNetbootGUID)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
{
PropertyValueCollection netbootGUIDProp = machineDE.Properties["netbootGUID"];
bool flag = netbootGUIDProp.Count > 0;
if (flag)
{
netbootGUIDProp.Clear();
}
netbootGUIDProp.Add(updatedNetbootGUID.ToByteArray());
machineDE.CommitChanges();
}
}
public static void SetDescription(this ActiveDirectoryMachineAccount account, string Description)
{
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
{
PropertyValueCollection descriptionProp = machineDE.Properties["description"];
if (descriptionProp.Count > 0)
{
descriptionProp.Clear();
}
if (!string.IsNullOrEmpty(Description))
{
descriptionProp.Add(Description);
}
machineDE.CommitChanges();
}
}
public static void SetDescription(this ActiveDirectoryMachineAccount account, Device Device)
{
System.Text.StringBuilder descriptionBuilder = new System.Text.StringBuilder();
if (Device.AssignedUserId != null)
{
descriptionBuilder.Append(Device.AssignedUser.Id).Append(" (").Append(Device.AssignedUser.DisplayName).Append("); ");
}
if (Device.DeviceModelId.HasValue)
{
descriptionBuilder.Append(Device.DeviceModel.Description).Append("; ");
}
descriptionBuilder.Append(Device.DeviceProfile.Description).Append(";");
string description = descriptionBuilder.ToString().Trim();
if (description.Length > 1024)
{
description = description.Substring(0, 1024);
}
account.SetDescription(description);
}
public static void DisableAccount(this ActiveDirectoryMachineAccount account)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
{
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
int updatedAccountControl = (accountControl | 2);
if (accountControl != updatedAccountControl)
{
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
machineDE.CommitChanges();
}
}
}
public static void EnableAccount(this ActiveDirectoryMachineAccount account)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
using (DirectoryEntry machineDE = new DirectoryEntry(account.Path))
{
int accountControl = (int)machineDE.Properties["userAccountControl"][0];
if ((accountControl & 2) == 2)
{
int updatedAccountControl = (accountControl ^ 2);
machineDE.Properties["userAccountControl"][0] = updatedAccountControl;
machineDE.CommitChanges();
}
}
}
public static bool UpdateNetbootGUID(this ActiveDirectoryMachineAccount account, string UUID, string MACAddress)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
System.Guid netbootGUID = System.Guid.Empty;
bool flag = !string.IsNullOrWhiteSpace(UUID);
if (flag)
{
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromUUID(UUID);
}
else
{
flag = !string.IsNullOrWhiteSpace(MACAddress);
if (flag)
{
netbootGUID = ActiveDirectoryMachineAccountExtensions.NetbootGUIDFromMACAddress(MACAddress);
}
}
flag = (netbootGUID != System.Guid.Empty && netbootGUID != account.NetbootGUID);
bool UpdateNetbootGUID;
if (flag)
{
account.SetNetbootGUID(netbootGUID);
UpdateNetbootGUID = true;
}
else
{
UpdateNetbootGUID = false;
}
return UpdateNetbootGUID;
}
internal static System.Guid NetbootGUIDFromMACAddress(string MACAddress)
{
string strippedMACAddress = MACAddress.Trim().Replace(":", string.Empty).Replace("-", string.Empty);
bool flag = strippedMACAddress.Length == 12;
System.Guid NetbootGUIDFromMACAddress;
if (flag)
{
System.Guid guid = new System.Guid(string.Format("00000000-0000-0000-0000-{0}", strippedMACAddress));
NetbootGUIDFromMACAddress = guid;
}
else
{
NetbootGUIDFromMACAddress = System.Guid.Empty;
}
return NetbootGUIDFromMACAddress;
}
internal static System.Guid NetbootGUIDFromUUID(string UUID)
{
System.Guid result = new System.Guid(UUID);
return result;
}
public static object GetPropertyValue(this ActiveDirectoryMachineAccount account, string PropertyName, int Index = 0)
{
switch (PropertyName.ToLower())
{
case "name":
return account.Name;
case "samaccountname":
return account.sAMAccountName;
case "distinguishedname":
return account.DistinguishedName;
case "objectsid":
return account.ObjectSid;
case "netbootguid":
return account.NetbootGUID;
default:
object[] adProperty;
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
return adProperty[Index];
else
return null;
}
}
public static IPStatus PingComputer(this ActiveDirectoryMachineAccount account, int Timeout = 2000)
{
using (var p = new Ping())
{
PingReply reply = p.Send(account.DnsName, Timeout);
return reply.Status;
}
}
// Didn't Work - WMI Limitation?
// G# - 2012-06-18
//public static void OnlineRenameComputer(this ActiveDirectoryMachineAccount account, string NewComputerName)
//{
// if (account.IsCriticalSystemObject)
// throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
// try
// {
// IPStatus pingResult = account.PingComputer();
// if (pingResult != IPStatus.Success)
// throw new Exception(string.Format("Ping Error Result: {0}", pingResult.ToString()));
// }
// catch (Exception ex)
// {
// throw new Exception(string.Format("Error trying to Ping the Device: {0}; {1}", account.DnsName, ex.Message), ex);
// }
// ConnectionOptions wmiConnectionOptions = new ConnectionOptions()
// {
// Authentication = AuthenticationLevel.PacketPrivacy,
// Impersonation = ImpersonationLevel.Impersonate,
// EnablePrivileges = true,
// Timeout = new TimeSpan(0, 0, 6)
// };
// ManagementPath wmiPath = new ManagementPath()
// {
// Server = account.DnsName,
// NamespacePath = @"root\cimv2",
// ClassName = "Win32_ComputerSystem"
// };
// ManagementScope wmiScope = new ManagementScope(wmiPath, wmiConnectionOptions);
// ObjectGetOptions wmiGetOptions = new ObjectGetOptions() { Timeout = new TimeSpan(0, 1, 0) };
// using (ManagementClass wmiClass = new ManagementClass(wmiScope, wmiPath, wmiGetOptions))
// {
// foreach (ManagementObject wmiWin32ComputerSystem in wmiClass.GetInstances())
// {
// UInt32 result = (UInt32)wmiWin32ComputerSystem.InvokeMethod("Rename", new object[] { NewComputerName });
// if (result != 0)
// throw new Exception(string.Format("Error Renaming Computer; WMI Remote Method 'Rename' returned: {0}", result));
// }
// }
//}
public static void MoveOrganisationUnit(this ActiveDirectoryMachineAccount account, string NewOrganisationUnit)
{
if (account.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco refuses to modify it", account.DistinguishedName));
if (!account.ParentDistinguishedName.Equals(NewOrganisationUnit, StringComparison.InvariantCultureIgnoreCase))
{
string ouPath;
if (string.IsNullOrWhiteSpace(NewOrganisationUnit))
ouPath = string.Format("{0}CN=Computers,{1}", ActiveDirectoryHelpers.DefaultLdapPath, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
else
ouPath = string.Format("{0}{1},{2}", ActiveDirectoryHelpers.DefaultLdapPath, NewOrganisationUnit, ActiveDirectoryHelpers.DefaultDomainQualifiedName);
using (DirectoryEntry ou = new DirectoryEntry(ouPath))
{
using (DirectoryEntry i = new DirectoryEntry(account.Path) { UsePropertyCache = false })
{
i.MoveTo(ou);
}
}
}
}
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.BI.Interop.ActiveDirectory
{
public class ActiveDirectoryOrganisationalUnit
{
public string Name { get; set; }
public string Path { get; set; }
public List<ActiveDirectoryOrganisationalUnit> Children { get; set; }
}
}
@@ -1,264 +0,0 @@
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Models.Repository;
using Quartz;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices;
using System.Linq;
using System.Linq.Expressions;
using System.Net.NetworkInformation;
using System.Reflection;
using Disco.Services.Tasks;
namespace Disco.BI.Interop.ActiveDirectory
{
public class ActiveDirectoryUpdateLastNetworkLogonDateJob : ScheduledTask
{
public override string TaskName { get { return "Active Directory - Update Last Network Logon Dates Task"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
{
// ActiveDirectoryUpdateLastNetworkLogonDateJob @ 11:30pm
TriggerBuilder triggerBuilder = TriggerBuilder.Create().
WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 30));
this.ScheduleTask(triggerBuilder);
}
protected override void ExecuteTask()
{
int changeCount;
this.Status.UpdateStatus(1, "Starting", "Connecting to the Database and initializing the environment");
using (DiscoDataContext dbContext = new DiscoDataContext())
{
UpdateLastNetworkLogonDates(dbContext, this.Status);
this.Status.UpdateStatus(95, "Updating Database", "Writing last network logon dates to the Database");
changeCount = dbContext.SaveChanges();
this.Status.Finished(string.Format("{0} Device last network logon dates updated", changeCount), "/Config/SystemConfig");
}
SystemLog.LogInformation(new string[]
{
"Updated LastNetworkLogon Device Property for Device/s",
changeCount.ToString()
});
}
public static ScheduledTaskStatus ScheduleImmediately()
{
var existingTask = ScheduledTasks.GetTaskStatuses(typeof(ActiveDirectoryUpdateLastNetworkLogonDateJob)).Where(s => s.IsRunning).FirstOrDefault();
if (existingTask != null)
return existingTask;
var instance = new ActiveDirectoryUpdateLastNetworkLogonDateJob();
return instance.ScheduleTask();
}
public static bool UpdateLastNetworkLogonDate(Device Device)
{
System.DateTime? computerLastLogonDate = Device.LastNetworkLogonDate;
if (!string.IsNullOrEmpty(Device.ComputerName))
{
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
{
try
{
Ping p = new Ping();
PingReply pr;
try
{
pr = p.Send(dcName, 500);
}
finally
{
if (p != null)
{
((System.IDisposable)p).Dispose();
}
}
if (pr.Status == IPStatus.Success)
{
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
{
DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, string.Format("(&(objectClass=computer)(sAMAccountName={0}$))", ActiveDirectoryHelpers.EscapeLdapQuery(Device.ComputerName)), new string[]
{
"lastLogon"
}, SearchScope.Subtree);
SearchResult dResult = dSearcher.FindOne();
if (dResult != null)
{
ResultPropertyValueCollection dProp = dResult.Properties["lastLogon"];
if (dProp != null && dProp.Count > 0)
{
long lastLogonInt = (long)dProp[0];
if (lastLogonInt > 0L)
{
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
if (computerLastLogonDate.HasValue)
{
if (System.DateTime.Compare(computerLastLogonDate.Value, computerNameDate) < 0)
{
computerLastLogonDate = computerNameDate;
}
}
else
{
computerLastLogonDate = computerNameDate;
}
}
}
}
}
}
else
{
SystemLog.LogError(new string[]
{
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateDeviceLastNetworkLogonDate)", dcName)
});
}
}
catch (System.Exception ex)
{
SystemLog.LogException("UpdateDeviceLastNetworkLogonDate", ex);
}
}
}
bool UpdateLastNetworkLogonDate;
if (computerLastLogonDate.HasValue)
{
if (!Device.LastNetworkLogonDate.HasValue)
{
Device.LastNetworkLogonDate = computerLastLogonDate;
UpdateLastNetworkLogonDate = true;
return UpdateLastNetworkLogonDate;
}
if (System.DateTime.Compare(computerLastLogonDate.Value, Device.LastNetworkLogonDate.Value) > 0)
{
Device.LastNetworkLogonDate = computerLastLogonDate;
UpdateLastNetworkLogonDate = true;
return UpdateLastNetworkLogonDate;
}
}
UpdateLastNetworkLogonDate = false;
return UpdateLastNetworkLogonDate;
}
private static void UpdateLastNetworkLogonDates(DiscoDataContext context, ScheduledTaskStatus status)
{
System.Collections.Generic.Dictionary<string, System.DateTime> computerLastLogonDates = new System.Collections.Generic.Dictionary<string, System.DateTime>();
int progressDCCountTotal = ActiveDirectoryHelpers.DefaultDomainDCNames.Count;
int progressDCCount = 0;
double progressDCProgress = 0;
if (progressDCCountTotal > 0)
progressDCProgress = 90 / progressDCCountTotal;
foreach (var dcName in ActiveDirectoryHelpers.DefaultDomainDCNames)
{
try
{
PingReply pr;
using (Ping p = new Ping())
{
pr = p.Send(dcName, 2000);
}
if (pr.Status == IPStatus.Success)
{
using (DirectoryEntry dRootEntry = ActiveDirectoryHelpers.DefaultDCLdapRoot(dcName))
{
double progressDCStart = 5 + (progressDCCount * progressDCProgress);
status.UpdateStatus(progressDCStart, string.Format("Querying Domain Controller: {0}", dcName), "Searching...");
using (DirectorySearcher dSearcher = new DirectorySearcher(dRootEntry, "(objectClass=computer)", new string[] { "sAMAccountName", "lastLogon" }, SearchScope.Subtree))
{
using (SearchResultCollection dResults = dSearcher.FindAll())
{
int progressItemCount = 0;
double progressItemProgress = dResults.Count == 0 ? 0 : (progressDCProgress / dResults.Count);
foreach (SearchResult dResult in dResults)
{
ResultPropertyValueCollection dProp = dResult.Properties["sAMAccountName"];
if (dProp != null && dProp.Count > 0)
{
string computerName = ((string)dProp[0]).TrimEnd(new char[] { '$' }).ToUpper();
if (progressItemCount % 150 == 0) // Only Update Status every 150 devices
status.UpdateStatus(progressDCStart + (progressItemProgress * progressItemCount), string.Format("Analysing Device: {0}", computerName));
dProp = dResult.Properties["lastLogon"];
if (dProp != null && dProp.Count > 0)
{
long lastLogonInt = (long)dProp[0];
if (lastLogonInt > 0L)
{
System.DateTime computerNameDate = System.DateTime.FromFileTime(lastLogonInt);
System.DateTime existingDate;
if (computerLastLogonDates.TryGetValue(computerName, out existingDate))
{
if (System.DateTime.Compare(existingDate, computerNameDate) < 0)
{
computerLastLogonDates[computerName] = computerNameDate;
}
}
else
{
computerLastLogonDates[computerName] = computerNameDate;
}
}
}
}
progressItemCount++;
}
}
}
}
}
else
{
SystemLog.LogError(new string[]
{
string.Format("Unable to ping Domain Controller: '{0}' (ref: Disco.BI.Interop.ActiveDirectory.ActiveDirectoryUpdateLastNetworkLogonDateJob.UpdateLastNetworkLogonDates)", dcName)
});
}
}
catch (System.Exception ex)
{
SystemLog.LogException("UpdateLastNetworkLogonDates", ex);
}
progressDCCount++;
}
foreach (Device d in context.Devices.Where(device => device.ComputerName != null))
{
DateTime computerLastLogonDate;
if (computerLastLogonDates.TryGetValue(d.ComputerName.ToUpper(), out computerLastLogonDate))
{
if (d.LastNetworkLogonDate.HasValue)
{
// Change accuracy to the second
computerLastLogonDate = new DateTime((computerLastLogonDate.Ticks / 10000000L) * 10000000L);
if (System.DateTime.Compare(d.LastNetworkLogonDate.Value, computerLastLogonDate) < 0)
{
d.LastNetworkLogonDate = computerLastLogonDate;
}
}
else
{
d.LastNetworkLogonDate = computerLastLogonDate;
}
}
}
}
}
}
@@ -1,42 +0,0 @@
using Disco.Models.Interop.ActiveDirectory;
using System;
using Disco.Models.Repository;
namespace Disco.BI.Interop.ActiveDirectory
{
internal static class ActiveDirectoryUserAccountExtensions
{
public static bool HasRole(this ActiveDirectoryUserAccount account, string Role)
{
return account.Groups != null && account.Groups.Contains(Role.ToLower());
}
public static object GetPropertyValue(this ActiveDirectoryUserAccount account, string PropertyName, int Index = 0)
{
switch (PropertyName.ToLower())
{
case "name":
return account.Name;
case "samaccountname":
return account.sAMAccountName;
case "distinguishedname":
return account.DistinguishedName;
case "objectsid":
return account.ObjectSid;
case "sn":
return account.Surname;
case "givenname":
return account.GivenName;
case "mail":
return account.Email;
case "telephonenumber":
return account.Phone;
default:
object[] adProperty;
if (account.LoadedProperties.TryGetValue(PropertyName, out adProperty) && Index <= adProperty.Length)
return adProperty[Index];
else
return null;
}
}
}
}
+30 -31
View File
@@ -1,16 +1,14 @@
using System;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Models.Repository;
using Disco.Services.Tasks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.Serialization;
using Disco.Data.Repository;
using Disco.Models.BI.Interop.Community;
using Disco.Services.Tasks;
using Newtonsoft.Json;
namespace Disco.BI.Interop.Community
{
@@ -31,16 +29,13 @@ namespace Disco.BI.Interop.Community
return string.Format("{0}.{1}.{2:0000}.{3:0000}", v.Major, v.Minor, v.Build, v.Revision);
}
public static UpdateResponse Check(DiscoDataContext db, bool UseProxy, ScheduledTaskStatus status = null)
public static UpdateResponse Check(DiscoDataContext Database, bool UseProxy, IScheduledTaskStatus status)
{
if (status != null)
status.UpdateStatus(10, "Building Update Request");
status.UpdateStatus(10, "Building Update Request");
var request = BuildRequest(db);
//var requestJson = JsonConvert.SerializeObject(request);
var request = BuildRequest(Database);
if (status != null)
status.UpdateStatus(40, "Sending Request");
status.UpdateStatus(40, "Sending Request");
var DiscoBIVersion = CurrentDiscoVersionFormatted();
@@ -63,23 +58,20 @@ namespace Disco.BI.Interop.Community
XmlSerializer xml = new XmlSerializer(typeof(UpdateRequestV1));
xml.Serialize(wrStream, request);
}
if (status != null)
status.UpdateStatus(50, "Waiting for Response");
status.UpdateStatus(50, "Waiting for Response");
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
if (status != null)
status.UpdateStatus(90, "Reading Response");
status.UpdateStatus(90, "Reading Response");
UpdateResponse result;
using (var wResStream = webResponse.GetResponseStream())
{
XmlSerializer xml = new XmlSerializer(typeof(UpdateResponse));
result = (UpdateResponse)xml.Deserialize(wResStream);
}
//var result = JsonConvert.DeserializeObject<UpdateResponse>(responseContent);
db.DiscoConfiguration.UpdateLastCheck = result;
db.SaveChanges();
Database.DiscoConfiguration.UpdateLastCheck = result;
Database.SaveChanges();
status.SetFinishedMessage(string.Format("The update server reported Version {0} is the latest.", result.Version));
@@ -87,30 +79,37 @@ namespace Disco.BI.Interop.Community
}
else
{
if (status != null)
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
return null;
}
}
}
private static UpdateRequestV1 BuildRequest(DiscoDataContext db)
private static UpdateRequestV1 BuildRequest(DiscoDataContext Database)
{
var m = new UpdateRequestV1();
m.DeploymentId = db.DiscoConfiguration.DeploymentId;
m.DeploymentId = Database.DiscoConfiguration.DeploymentId;
m.CurrentDiscoVersion = CurrentDiscoVersionFormatted();
m.OrganisationName = db.DiscoConfiguration.OrganisationName;
m.OrganisationName = Database.DiscoConfiguration.OrganisationName;
m.BroadbandDoeWanId = GetBroadbandDoeWanId();
m.BetaDeployment = db.DiscoConfiguration.UpdateBetaDeployment;
m.BetaDeployment = Database.DiscoConfiguration.UpdateBetaDeployment;
m.Stat_JobCounts = db.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_OpenJobCounts = db.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_JobCounts = Database.Jobs.GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_OpenJobCounts = Database.Jobs.Where(j => j.ClosedDate == null).GroupBy(j => j.JobTypeId).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_DeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null) }).ToList();
var activeThreshold = DateTime.Now.AddDays(-60);
m.Stat_ActiveDeviceModelCounts = db.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = db.Users.GroupBy(u => u.Type).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key, Count = g.Count() }).ToList();
m.Stat_ActiveDeviceModelCounts = Database.DeviceModels.Select(dm => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = dm.Manufacturer + ";" + dm.Model, Count = dm.Devices.Count(d => d.DecommissionedDate == null && (d.LastNetworkLogonDate == null || d.LastNetworkLogonDate > activeThreshold)) }).ToList();
m.Stat_UserCounts = new List<UpdateRequestV1.Stat>() {
new UpdateRequestV1.Stat(){
Key = "All Users",
Count = Database.Users.Count()
}
};
m.Stat_JobWarrantyVendorCounts = Database.Jobs.Where(j => j.JobTypeId == JobType.JobTypeIds.HWar && j.JobMetaWarranty.ExternalLoggedDate.HasValue && j.JobMetaWarranty.ExternalName != null).GroupBy(j => j.JobMetaWarranty.ExternalName).Select(g => new Disco.Models.BI.Interop.Community.UpdateRequestV1.Stat { Key = g.Key ?? "<Unknown>", Count = g.Count() }).ToList();
m.InstalledPlugins = Disco.Services.Plugins.Plugins.GetPlugins().Select(manifest => new Disco.Models.BI.Interop.Community.UpdateRequestV1.PluginRef { Id = manifest.Id, Version = manifest.VersionFormatted }).ToList();
@@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using Disco.Services.Logging;
using Disco.Data.Repository;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.Linq;
namespace Disco.BI.Interop.Community
{
@@ -53,7 +49,7 @@ namespace Disco.BI.Interop.Community
}
}
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext dbContext)
public override void InitalizeScheduledTask(Data.Repository.DiscoDataContext Database)
{
// Random time between midday and midnight.
var rnd = new Random();
@@ -69,17 +65,17 @@ namespace Disco.BI.Interop.Community
protected override void ExecuteTask()
{
using (DiscoDataContext db = new DiscoDataContext())
using (DiscoDataContext database = new DiscoDataContext())
{
try
{
UpdateCheck.Check(db, true, this.Status);
UpdateCheck.Check(database, true, this.Status);
}
catch (Exception ex)
{
ScheduledTasksLog.LogScheduledTaskException(this.Status.TaskName, this.Status.SessionId, this.Status.TaskType, ex);
// Could be proxy error - try again without proxy:
UpdateCheck.Check(db, false, this.Status);
UpdateCheck.Check(database, false, this.Status);
}
}
}
+32 -29
View File
@@ -1,24 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.Repository;
using Disco.BI.Expressions;
using Disco.BI.Extensions;
using Disco.Data.Repository;
using Disco.Models.BI.DocumentTemplates;
using System.IO;
using iTextSharp.text.pdf;
using System.Collections.Concurrent;
using Disco.BI.Expressions;
using System.Collections;
using Disco.BI.Extensions;
using Disco.Models.BI.Expressions;
using Disco.Models.Repository;
using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Users;
using iTextSharp.text.pdf;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Disco.BI.Interop.Pdf
{
public static class PdfGenerator
{
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext dbContext, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params object[] DataObjects)
{
if (DataObjects.Length > 0)
{
@@ -27,7 +28,7 @@ namespace Disco.BI.Interop.Pdf
{
foreach (object d in DataObjects)
{
generatedPdfs.Add(dt.GeneratePdf(dbContext, d, CreatorUser, Timestamp, state, true));
generatedPdfs.Add(dt.GeneratePdf(Database, d, CreatorUser, Timestamp, state, true));
state.SequenceNumber++;
state.FlushScopeCache();
}
@@ -47,36 +48,38 @@ namespace Disco.BI.Interop.Pdf
return null;
}
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext dbContext, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
public static System.IO.Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, System.DateTime Timestamp, params string[] DataObjectsIds)
{
object[] DataObjects;
switch (dt.Scope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
DataObjects = dbContext.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToArray();
DataObjects = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToArray();
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
int[] intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToArray();
DataObjects = dbContext.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToArray();
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToArray();
break;
case DocumentTemplate.DocumentTemplateScopes.User:
DataObjects = new object[DataObjectsIds.Length];
for (int idIndex = 0; idIndex < DataObjectsIds.Length; idIndex++)
{
DataObjects[idIndex] = UserBI.UserCache.GetUser(DataObjectsIds[idIndex], dbContext, true);
string dataObjectId = DataObjectsIds[idIndex];
DataObjects[idIndex] = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
if (DataObjects[idIndex] == null)
throw new Exception(string.Format("Unknown Username specified: {0}", DataObjectsIds[idIndex]));
throw new Exception(string.Format("Unknown Username specified: {0}", dataObjectId));
}
break;
default:
throw new InvalidOperationException("Invalid DocumentType Scope");
}
return GenerateBulkFromTemplate(dt, dbContext, CreatorUser, Timestamp, DataObjects);
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, DataObjects);
}
public static System.IO.Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext dbContext, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
public static System.IO.Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, object Data, User CreatorUser, System.DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
{
// Validate Data
switch (dt.Scope)
@@ -97,15 +100,15 @@ namespace Disco.BI.Interop.Pdf
throw new InvalidOperationException("Invalid AttachmentType Scope");
}
dbContext.Configuration.LazyLoadingEnabled = true;
Database.Configuration.LazyLoadingEnabled = true;
// Override FlattenFields if Document Template instructs.
if (dt.FlattenForm)
FlattenFields = true;
ConcurrentDictionary<string, Expression> expressionCache = dt.PdfExpressionsFromCache(dbContext);
ConcurrentDictionary<string, Expression> expressionCache = dt.PdfExpressionsFromCache(Database);
string templateFilename = dt.RepositoryFilename(dbContext);
string templateFilename = dt.RepositoryFilename(Database);
PdfReader pdfReader = new PdfReader(templateFilename);
MemoryStream pdfGeneratedStream = new MemoryStream();
@@ -114,14 +117,14 @@ namespace Disco.BI.Interop.Pdf
pdfStamper.FormFlattening = FlattenFields;
pdfStamper.Writer.CloseStream = false;
IDictionary expressionVariables = Expression.StandardVariables(dt, dbContext, CreatorUser, TimeStamp, State);
IDictionary expressionVariables = Expression.StandardVariables(dt, Database, CreatorUser, TimeStamp, State);
foreach (string pdfFieldKey in pdfStamper.AcroFields.Fields.Keys)
{
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.InvariantCultureIgnoreCase))
if (pdfFieldKey.Equals("DiscoAttachmentId", StringComparison.OrdinalIgnoreCase))
{
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.Id, TimeStamp);
string fieldValue = dt.UniqueIdentifier(Data, CreatorUser.UserId, TimeStamp);
if (FlattenFields)
pdfStamper.AcroFields.SetField(pdfFieldKey, String.Empty);
else
@@ -131,7 +134,7 @@ namespace Disco.BI.Interop.Pdf
for (int pdfFieldOrdinal = 0; pdfFieldOrdinal < fields.Size; pdfFieldOrdinal++)
{
AcroFields.FieldPosition pdfFieldPosition = pdfFieldPositions[pdfFieldOrdinal];
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.Id, TimeStamp, pdfFieldPosition.page);
string pdfBarcodeContent = dt.UniquePageIdentifier(Data, CreatorUser.UserId, TimeStamp, pdfFieldPosition.page);
BarcodeQRCode pdfBarcode = new BarcodeQRCode(pdfBarcodeContent, (int)pdfFieldPosition.position.Width, (int)pdfFieldPosition.position.Height, null);
iTextSharp.text.Image pdfBarcodeImage = pdfBarcode.GetImage();
pdfBarcodeImage.SetAbsolutePosition(pdfFieldPosition.position.Left, pdfFieldPosition.position.Bottom);
@@ -236,11 +239,11 @@ namespace Disco.BI.Interop.Pdf
JobLog jl = new JobLog()
{
JobId = j.Id,
TechUserId = CreatorUser.Id,
TechUserId = CreatorUser.UserId,
Timestamp = DateTime.Now
};
jl.Comments = string.Format("Document Generated{0}{1} [{2}]", Environment.NewLine, dt.Description, dt.Id);
dbContext.JobLogs.Add(jl);
Database.JobLogs.Add(jl);
}
pdfGeneratedStream.Position = 0;
+16 -16
View File
@@ -205,7 +205,7 @@ namespace Disco.BI.Interop.Pdf
return null;
}
private static DetectImageResult DetectImage(DiscoDataContext dbContext, Bitmap pageImageOriginal, string SessionId, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
private static DetectImageResult DetectImage(DiscoDataContext Database, Bitmap pageImageOriginal, string SessionId, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
{
Bitmap pageImage = pageImageOriginal;
double pageImageModifiedScale = 1;
@@ -270,7 +270,7 @@ namespace Disco.BI.Interop.Pdf
{
foreach (DocumentTemplate dt in detectDocumentTemplates)
{
var locationBag = dt.QRCodeLocations(dbContext);
var locationBag = dt.QRCodeLocations(Database);
foreach (var location in locationBag)
{
result = DetectImageFromSegment(pageImage, zxingMfr, zxingMfrHints,
@@ -303,7 +303,7 @@ namespace Disco.BI.Interop.Pdf
}
}
private static DetectPageResult DetectPage(DiscoDataContext dbContext, PdfReader pdfReader, int PageNumber, string SessionId, string DataStoreSessionCacheLocation, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
private static DetectPageResult DetectPage(DiscoDataContext Database, PdfReader pdfReader, int PageNumber, string SessionId, string DataStoreSessionCacheLocation, IEnumerable<DocumentTemplate> detectDocumentTemplates, DetectStateHints StateHints)
{
DetectPageResult result = new DetectPageResult() { PageNumber = PageNumber };
@@ -325,7 +325,7 @@ namespace Disco.BI.Interop.Pdf
{
DocumentImporterLog.LogImportPageProgress(SessionId, PageNumber, (int)(10 + (pageProgressInterval * pageImages.IndexOf(pageImageOriginal))), String.Format("Processing Page Image {0} of {1}", pageImages.IndexOf(pageImageOriginal) + 1, pageImages.Count));
using (var zxingResult = DetectImage(dbContext, pageImageOriginal, SessionId, detectDocumentTemplates, StateHints))
using (var zxingResult = DetectImage(Database, pageImageOriginal, SessionId, detectDocumentTemplates, StateHints))
{
if (zxingResult != null)
{
@@ -377,9 +377,9 @@ namespace Disco.BI.Interop.Pdf
}
}
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext dbContext, string SessionId, Cache HttpCache)
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string SessionId, Cache HttpCache)
{
var dataStoreUnassignedLocation = DataStore.CreateLocation(dbContext, "DocumentDropBox_Unassigned");
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
DocumentImporterLog.LogImportProgress(SessionId, 0, "Reading File");
@@ -389,8 +389,8 @@ namespace Disco.BI.Interop.Pdf
var pdfPagesAssigned = new Dictionary<int, Tuple<DocumentUniqueIdentifier, byte[]>>();
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(dbContext, "Cache\\DocumentDropBox_SessionPages");
var detectDocumentTemplates = dbContext.DocumentTemplates.ToArray();
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
var detectDocumentTemplates = Database.DocumentTemplates.ToArray();
double progressInterval = 70 / pdfReader.NumberOfPages;
@@ -401,15 +401,15 @@ namespace Disco.BI.Interop.Pdf
DocumentImporterLog.LogImportProgress(SessionId, (int)(PageNumber * progressInterval), string.Format("Processing Page {0} of {1}", PageNumber, pdfReader.NumberOfPages));
DocumentImporterLog.LogImportPageStarting(SessionId, PageNumber);
using (var pageResult = DetectPage(dbContext, pdfReader, PageNumber, SessionId, dataStoreSessionPagesCacheLocation, detectDocumentTemplates, detectStateHints))
using (var pageResult = DetectPage(Database, pdfReader, PageNumber, SessionId, dataStoreSessionPagesCacheLocation, detectDocumentTemplates, detectStateHints))
{
if (pageResult.DetectedIdentifier != null)
{
var docId = pageResult.DetectedIdentifier;
pdfPagesAssigned.Add(PageNumber, new Tuple<DocumentUniqueIdentifier, byte[]>(docId, pageResult.AttachmentThumbnailImage.ToArray()));
docId.LoadComponents(dbContext);
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.DocumentUniqueId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
docId.LoadComponents(Database);
DocumentImporterLog.LogImportPageDetected(SessionId, PageNumber, docId.TemplateTypeId, docId.DocumentTemplate.Description, docId.DocumentTemplate.Scope, docId.DataId, docId.DataDescription);
}
else
{
@@ -441,7 +441,7 @@ namespace Disco.BI.Interop.Pdf
var documentPortionIdentifier = documentPortionInfo.Item1;
var documentPortionThumbnail = documentPortionInfo.Item2;
if (!documentPortionIdentifier.LoadComponents(dbContext))
if (!documentPortionIdentifier.LoadComponents(Database))
{
// Unknown Document Unique Id
foreach (var dp in documentPortion)
@@ -477,7 +477,7 @@ namespace Disco.BI.Interop.Pdf
msBuilder.Position = 0;
var attachmentSuccess = documentPortionIdentifier.ImportPdfAttachment(dbContext, msBuilder, documentPortionThumbnail);
var attachmentSuccess = documentPortionIdentifier.ImportPdfAttachment(Database, msBuilder, documentPortionThumbnail);
if (!attachmentSuccess)
{ // Unable to add Attachment
@@ -538,13 +538,13 @@ namespace Disco.BI.Interop.Pdf
return true;
}
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext dbContext, string DocumentTemplateId, string DataId, string UserId, DateTime Timestamp)
public static bool ProcessPdfAttachment(string Filename, DiscoDataContext Database, string DocumentTemplateId, string DataId, string UserId, DateTime Timestamp)
{
using (FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
DocumentUniqueIdentifier identifier = new DocumentUniqueIdentifier(DocumentTemplateId, DataId, UserId, Timestamp);
identifier.LoadComponents(dbContext);
return identifier.ImportPdfAttachment(dbContext, fs, null);
identifier.LoadComponents(Database);
return identifier.ImportPdfAttachment(Database, fs, null);
}
}
@@ -1,14 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Disco.Data.Repository;
//using Quartz;
//namespace Disco.BI.Interop.PluginServices
//{
// interface IDiscoScheduledTask
// {
// void InitalizeScheduledTask(DiscoDataContext dbContext, IScheduler Scheduler);
// }
//}
@@ -1,45 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Disco.Data.Repository;
//using Quartz;
//namespace Disco.BI.Interop.PluginServices
//{
// public static class Utilities
// {
// public static void InitalizeScheduledTasks(DiscoDataContext dbContext, ISchedulerFactory SchedulerFactory)
// {
// var scheduler = SchedulerFactory.GetScheduler();
// // Discover IDiscoScheduledTasks (Only from Disco Assemblies)
// var appDomain = AppDomain.CurrentDomain;
// var scheduledTaskTypes = (from a in appDomain.GetAssemblies()
// where !a.GlobalAssemblyCache && !a.IsDynamic && a.FullName.StartsWith("Disco.", StringComparison.InvariantCultureIgnoreCase)
// from type in a.GetTypes()
// where typeof(IDiscoScheduledTask).IsAssignableFrom(type) && !type.IsAbstract
// select type);
// foreach (Type scheduledTaskType in scheduledTaskTypes)
// {
// IDiscoScheduledTask instance = (IDiscoScheduledTask)Activator.CreateInstance(scheduledTaskType);
// try
// {
// instance.InitalizeScheduledTask(dbContext, scheduler);
// }
// catch (Exception ex)
// {
// if (instance == null)
// Logging.SystemLog.LogException("Initializing Scheduled Task; Disco.BI.Interop.Plugins.Utilities.InitalizeScheduledTasks()", ex);
// else
// Logging.SystemLog.LogException(string.Format("Initializing Scheduled Task: '{0}'; Disco.BI.Interop.Plugins.Utilities.InitalizeScheduledTasks()", instance.GetType().Name), ex);
// }
// }
// }
// }
//}
@@ -1,16 +0,0 @@
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Interop.SignalRHandlers
{
public class AdminAuthorizedPersistentConnection : AuthorizedPersistentConnection
{
private string[] authorizedUserTypes = { User.Types.Admin };
protected override string[] AuthorizedUserTypes { get { return authorizedUserTypes; } }
}
}
@@ -1,36 +0,0 @@
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Interop.SignalRHandlers
{
public class AuthorizedPersistentConnection : PersistentConnection
{
private string[] authorizedUserTypes = null;
protected virtual string[] AuthorizedUserTypes { get { return authorizedUserTypes; } }
protected override bool AuthorizeRequest(IRequest request)
{
if (!request.User.Identity.IsAuthenticated)
return false;
else
{
var user = UserBI.UserCache.CurrentUser;
if (user == null)
return false;
if (AuthorizedUserTypes == null || AuthorizedUserTypes.Length == 0)
return true;
if (AuthorizedUserTypes.Contains(user.Type))
return true;
return false;
}
}
}
}
@@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNet.SignalR;
using System.Reactive.Linq;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
namespace Disco.BI.Interop.SignalRHandlers
{
public class HeldDeviceNotifications : PersistentConnection
{
private static bool subscribed = false;
private static object subscribeLock = new object();
private static IPersistentConnectionContext notificationContext;
static HeldDeviceNotifications()
{
if (!subscribed)
lock (subscribeLock)
if (!subscribed)
{
notificationContext = GlobalHost.ConnectionManager.GetConnectionContext<HeldDeviceNotifications>();
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e => e.EntityType == typeof(Job)).Subscribe(JobUpdated);
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(Device) &&
(e.ModifiedProperties.Contains("Location") ||
e.ModifiedProperties.Contains("DeviceModelId") ||
e.ModifiedProperties.Contains("DeviceProfileId") ||
e.ModifiedProperties.Contains("DeviceBatchId") ||
e.ModifiedProperties.Contains("ComputerName") ||
e.ModifiedProperties.Contains("AssignedUserId"))
).Subscribe(DeviceUpdated);
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(User) &&
e.ModifiedProperties.Contains("DisplayName")
).Subscribe(UserUpdated);
subscribed = true;
}
}
private static void JobUpdated(RepositoryMonitorEvent e)
{
Job j = (Job)e.Entity;
if (j.DeviceSerialNumber != null)
notificationContext.Connection.Broadcast(j.DeviceSerialNumber);
}
private static void DeviceUpdated(RepositoryMonitorEvent e)
{
Device d = (Device)e.Entity;
notificationContext.Connection.Broadcast(d.SerialNumber);
}
private static void UserUpdated(RepositoryMonitorEvent e)
{
User u = (User)e.Entity;
var userDevices = e.dbContext.Devices.Where(d => d.AssignedUserId == u.Id);
foreach (var userDevice in userDevices)
{
notificationContext.Connection.Broadcast(userDevice.SerialNumber);
}
}
}
}
@@ -1,76 +0,0 @@
using Disco.Services.Logging;
using Disco.Services.Logging.Models;
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Interop.SignalRHandlers
{
public class LogNotifications : AdminAuthorizedPersistentConnection
{
public static bool initialized = false;
public LogNotifications()
{
if (!initialized)
{
initialized = true;
Disco.Services.Logging.Targets.LogLiveContext.LogBroadcast += Broadcast;
}
}
protected override Task OnConnected(IRequest request, string connectionId)
{
string addToGroups = request.QueryString["addToGroups"];
if (!string.IsNullOrWhiteSpace(addToGroups))
{
var groups = addToGroups.Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnConnected(request, connectionId);
}
protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
{
// Add to Group
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
{
var groups = data.Substring(13).Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnReceived(request, connectionId, data);
}
internal static void Broadcast(LogBase logModule, LogEventType eventType, DateTime Timestamp, params object[] Arguments)
{
var message = LogLiveEvent.Create(logModule, eventType, Timestamp, Arguments);
var connectionManager = GlobalHost.ConnectionManager;
var connectionContext = connectionManager.GetConnectionContext<LogNotifications>();
connectionContext.Groups.Send(_GroupNameAll, message);
connectionContext.Groups.Send(logModule.ModuleName, message);
}
private const string _GroupNameAll = "__All";
public static string AllNotifications
{
get
{
return _GroupNameAll;
}
}
}
}
@@ -1,54 +0,0 @@
using Disco.Data.Repository.Monitor;
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Interop.SignalRHandlers
{
public class RepositoryMonitorNotifications : AdminAuthorizedPersistentConnection
{
public static void Initialize()
{
RepositoryMonitor.StreamAfterCommit.Subscribe(AfterCommit);
}
protected override Task OnConnected(IRequest request, string connectionId)
{
string addToGroups = request.QueryString["addToGroups"];
if (!string.IsNullOrWhiteSpace(addToGroups))
{
var groups = addToGroups.Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnConnected(request, connectionId);
}
protected override Task OnReceived(IRequest request, string connectionId, string data)
{
// Add to Group
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
{
var groups = data.Substring(13).Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnReceived(request, connectionId, data);
}
private static void AfterCommit(RepositoryMonitorEvent e)
{
GlobalHost.ConnectionManager.GetConnectionContext<RepositoryMonitorNotifications>().Groups.Send(e.EntityType.Name, e);
}
}
}
@@ -1,72 +0,0 @@
using Disco.Services.Tasks;
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.BI.Interop.SignalRHandlers
{
public class ScheduledTasksStatusNotifications : AdminAuthorizedPersistentConnection
{
public static bool initialized = false;
public ScheduledTasksStatusNotifications()
{
if (!initialized)
{
initialized = true;
Disco.Services.Tasks.ScheduledTaskStatus.UpdatedBroadcast += Broadcast;
}
}
protected override Task OnConnected(IRequest request, string connectionId)
{
string addToGroups = request.QueryString["addToGroups"];
if (!string.IsNullOrWhiteSpace(addToGroups))
{
var groups = addToGroups.Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnConnected(request, connectionId);
}
protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
{
// Add to Group
if (!string.IsNullOrWhiteSpace(data) && data.StartsWith("/addToGroups:") && data.Length > 13)
{
var groups = data.Substring(13).Split(',');
foreach (var g in groups)
{
this.Groups.Add(connectionId, g);
}
}
return base.OnReceived(request, connectionId, data);
}
internal static void Broadcast(ScheduledTaskStatusLive SessionStatus)
{
var connectionManager = GlobalHost.ConnectionManager;
var connectionContext = connectionManager.GetConnectionContext<ScheduledTasksStatusNotifications>();
connectionContext.Groups.Send(_GroupNameAll, SessionStatus);
connectionContext.Groups.Send(SessionStatus.SessionId, SessionStatus);
}
private const string _GroupNameAll = "__All";
public static string AllNotifications
{
get
{
return _GroupNameAll;
}
}
}
}
@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;
using Microsoft.AspNet.SignalR;
using Owin;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;
namespace Disco.BI.Interop.SignalRHandlers
{
/// <summary>
/// Required for SignalR 1.1.0 NTLM support in Firefox & Safari
/// Returns 401 (Unauthorized) instead of 403 (Forbidden) when an unauthenticated request is processed
///
/// TODO: Remove this workaround when implementing SignalR 2.x
///
/// Thanks to David Fowler (@davidfowl)
/// </summary>
public static class SignalRAuthenticationWorkaround
{
public static void AddMiddleware(IAppBuilder app)
{
Func<AppFunc, AppFunc> convert403To401 = Convert403To401;
app.Use(convert403To401);
}
private static AppFunc Convert403To401(AppFunc next)
{
return env =>
{
// Execute the SignalR pipeline
Task task = next(env);
// Get the status code
int statusCode = 0;
if (env.ContainsKey("owin.ResponseStatusCode"))
{
statusCode = (int)env["owin.ResponseStatusCode"];
}
// If its 403 then convert it to 401 (we shouldn't do
// this if it's a cross domain request since it doesn't make sense)
if (statusCode == 403)
{
env["owin.ResponseStatusCode"] = 401;
}
// Return the original task
return task;
};
}
}
}
@@ -1,82 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNet.SignalR;
using System.Reactive.Linq;
using Disco.Data.Repository.Monitor;
using Disco.Models.Repository;
namespace Disco.BI.Interop.SignalRHandlers
{
public class UserHeldDeviceNotifications : PersistentConnection
{
private static bool subscribed = false;
private static object subscribeLock = new object();
private static IPersistentConnectionContext notificationContext;
static UserHeldDeviceNotifications()
{
if (!subscribed)
lock (subscribeLock)
if (!subscribed)
{
notificationContext = GlobalHost.ConnectionManager.GetConnectionContext<UserHeldDeviceNotifications>();
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e => e.EntityType == typeof(Job)).Subscribe(JobUpdated);
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamBeforeCommit.Where(e =>
e.EntityType == typeof(Device) &&
(e.ModifiedProperties.Contains("DeviceModelId") ||
e.ModifiedProperties.Contains("DeviceProfileId") ||
e.ModifiedProperties.Contains("DeviceBatchId") ||
e.ModifiedProperties.Contains("AssignedUserId"))
).Subscribe(DeviceUpdated);
Disco.Data.Repository.Monitor.RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(User) &&
e.ModifiedProperties.Contains("DisplayName")
).Subscribe(UserUpdated);
subscribed = true;
}
}
private static void JobUpdated(RepositoryMonitorEvent e)
{
Job j = (Job)e.Entity;
if (j.DeviceSerialNumber != null)
{
var jobDevice = e.dbContext.Devices.Where(d => d.SerialNumber == j.DeviceSerialNumber).FirstOrDefault();
if (jobDevice.AssignedUserId != null)
notificationContext.Connection.Broadcast(jobDevice.AssignedUserId);
}
}
private static void DeviceUpdated(RepositoryMonitorEvent e)
{
Device d = (Device)e.Entity;
string previouslyAssignedUserId = null;
if (e.ModifiedProperties.Contains("AssignedUserId"))
previouslyAssignedUserId = e.GetPreviousPropertyValue<string>("AssignedUserId");
e.ExecuteAfterCommit(me =>
{
if (previouslyAssignedUserId != null)
notificationContext.Connection.Broadcast(previouslyAssignedUserId);
if (d.AssignedUserId != null)
notificationContext.Connection.Broadcast(d.AssignedUserId);
});
}
private static void UserUpdated(RepositoryMonitorEvent e)
{
User u = (User)e.Entity;
notificationContext.Connection.Broadcast(u.Id);
}
}
}
-135
View File
@@ -1,135 +0,0 @@
using Disco.Data.Repository;
using Disco.Data.Repository.Monitor;
using Disco.Models.BI.Job;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Disco.BI.Extensions;
using System.Reactive.Linq;
namespace Disco.BI.JobBI
{
public class ManagedJobList : JobTableModel, IDisposable
{
public string Name { get; set; }
public Func<IQueryable<Job>, IQueryable<Job>> FilterFunction { get; set; }
public Func<IEnumerable<JobTableItemModel>, IEnumerable<JobTableItemModel>> SortFunction { get; set; }
private IDisposable unsubscribeToken;
private object updateLock = new object();
public ManagedJobList Initialize(DiscoDataContext dbContext)
{
// Initially fill table
this.Items = this.SortFunction(this.DetermineItems(dbContext, this.FilterFunction(dbContext.Jobs))).ToList();
// Subscribe for Changes
// - Job (or Job Meta) Changes
// - Device Profile Address Changes (for multi-campus Schools)
// - Device Model Description Changes
// - Device's Profile or Model Changes
unsubscribeToken = RepositoryMonitor.StreamAfterCommit
.Where(n => n.EntityType == typeof(Job) ||
n.EntityType == typeof(JobMetaWarranty) ||
n.EntityType == typeof(JobMetaNonWarranty) ||
n.EntityType == typeof(JobMetaInsurance) ||
(n.EventType == RepositoryMonitorEventType.Modified && (
(n.EntityType == typeof(DeviceProfile) && n.ModifiedProperties.Contains("DefaultOrganisationAddress")) ||
(n.EntityType == typeof(DeviceModel) && n.ModifiedProperties.Contains("Description")) ||
(n.EntityType == typeof(Device) && n.ModifiedProperties.Contains("DeviceProfileId") || n.ModifiedProperties.Contains("DeviceModelId"))
)))
.Subscribe(JobNotification);
return this;
}
private void JobNotification(RepositoryMonitorEvent e)
{
List<int> jobIds = null;
JobTableItemModel[] existingItems = null;
if (e.EntityType == typeof(Job))
jobIds = new List<int>() { ((Job)e.Entity).Id };
else
if (e.EntityType == typeof(JobMetaWarranty))
jobIds = new List<int>() { ((JobMetaWarranty)e.Entity).JobId };
else
if (e.EntityType == typeof(JobMetaNonWarranty))
jobIds = new List<int>() { ((JobMetaNonWarranty)e.Entity).JobId };
else
if (e.EntityType == typeof(JobMetaInsurance))
jobIds = new List<int>() { ((JobMetaInsurance)e.Entity).JobId };
else
if (e.EntityType == typeof(DeviceProfile))
{
int deviceProfileId = ((DeviceProfile)e.Entity).Id;
existingItems = this.Items.Where(i => i.DeviceProfileId == deviceProfileId).ToArray();
}
else
if (e.EntityType == typeof(DeviceModel))
{
int deviceModelId = ((DeviceModel)e.Entity).Id;
existingItems = this.Items.Where(i => i.DeviceModelId == deviceModelId).ToArray();
}
else
if (e.EntityType == typeof(Device))
{
string deviceSerialNumber = ((Device)e.Entity).SerialNumber;
existingItems = this.Items.Where(i => i.DeviceSerialNumber == deviceSerialNumber).ToArray();
}
else
return; // Subscription should never reach
if (jobIds == null)
{
if (existingItems == null)
throw new InvalidOperationException("Notification algorithm didn't indicate any Jobs for update");
else
jobIds = existingItems.Select(i => i.Id).ToList();
}
if (jobIds.Count == 0)
return;
else
UpdateJobs(e.dbContext, jobIds, existingItems);
}
private void UpdateJobs(DiscoDataContext dbContext, List<int> jobIds, JobTableItemModel[] existingItems = null)
{
lock (updateLock)
{
// Check for existing items, if not handed them
if (existingItems == null)
existingItems = this.Items.Where(i => jobIds.Contains(i.Id)).ToArray();
var updatedItems = this.DetermineItems(dbContext, this.FilterFunction(dbContext.Jobs.Where(j => jobIds.Contains(j.Id))));
var refreshedList = this.Items.ToList();
// Remove Existing
if (existingItems.Length > 0)
foreach (var existingItem in existingItems)
refreshedList.Remove(existingItem);
// Add Updated Items
if (updatedItems.Count > 0)
foreach (var updatedItem in updatedItems)
refreshedList.Add(updatedItem);
// Reorder
this.Items = this.SortFunction(refreshedList).ToList();
}
}
public void Dispose()
{
if (unsubscribeToken != null)
{
unsubscribeToken.Dispose();
unsubscribeToken = null;
}
}
}
}
-93
View File
@@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Job;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Disco.BI.Extensions;
namespace Disco.BI.JobBI
{
public static class Searching
{
public static JobTableModel Search(DiscoDataContext dbContext, string Term, int? LimitCount = null, bool IncludeJobStatus = true, bool SearchDetails = false)
{
int termInt = default(int);
IQueryable<Job> query = default(IQueryable<Job>);
if (int.TryParse(Term, out termInt))
{
// Term is a Number (int)
if (SearchDetails)
{
query = BuildJobTableModel(dbContext).Where(j =>
j.Id == termInt ||
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.Id == Term ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)));
}
else
{
query = BuildJobTableModel(dbContext).Where(j =>
j.Id == termInt ||
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.Id == Term ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));
}
}
else
{
if (SearchDetails)
{
query = BuildJobTableModel(dbContext).Where(j =>
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.Id == Term ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term) ||
j.JobLogs.Any(jl => jl.Comments.Contains(Term)) ||
j.JobAttachments.Any(ja => ja.Comments.Contains(Term)));
}
else
{
query = BuildJobTableModel(dbContext).Where(j =>
j.DeviceHeldLocation.Contains(Term) ||
j.Device.SerialNumber.Contains(Term) ||
j.Device.AssetNumber.Contains(Term) ||
j.User.Id == Term ||
j.User.Surname.Contains(Term) ||
j.User.GivenName.Contains(Term) ||
j.User.DisplayName.Contains(Term));
}
}
if (LimitCount.HasValue)
query = query.Take(LimitCount.Value);
JobTableModel model = new JobTableModel() { ShowStatus = IncludeJobStatus };
model.Fill(dbContext, query);
return model;
}
public static IQueryable<Job> BuildJobTableModel(DiscoDataContext dbContext)
{
return dbContext.Jobs.Include("JobType").Include("Device").Include("User").Include("OpenedTechUser");
}
}
}
@@ -24,8 +24,9 @@ namespace Disco.BI.JobBI.Statistics
public override string TaskName { get { return "Job Statistics - Daily Opened/Closed Task"; } }
public override bool SingleInstanceTask { get { return true; } }
public override bool CancelInitiallySupported { get { return false; } }
public override bool LogExceptionsOnly { get { return true; } }
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
public override void InitalizeScheduledTask(DiscoDataContext Database)
{
// Trigger Daily @ 12:29am
TriggerBuilder triggerBuilder = TriggerBuilder.Create().WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 29));
@@ -34,40 +35,13 @@ namespace Disco.BI.JobBI.Statistics
}
protected override void ExecuteTask()
{
using (var dbContext = new DiscoDataContext())
using (var database = new DiscoDataContext())
{
UpdateDataHistory(dbContext, true);
UpdateDataHistory(database, true);
}
}
//public void InitalizeScheduledTask(DiscoDataContext dbContext, IScheduler Scheduler)
//{
// // Run @ 12:29am
// IJobDetail jobDetail = new JobDetailImpl("JobStatisticsDailyOpenedClosed", typeof(DailyOpenedClosed));
// ITrigger trigger = TriggerBuilder.Create().
// WithIdentity("JobStatisticsDailyOpenedClosedTrigger").
// StartNow().
// WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(0, 29)).
// Build();
// Scheduler.ScheduleJob(jobDetail, trigger);
//}
//public void Execute(IJobExecutionContext context)
//{
// try
// {
// using (var dbContext = new DiscoDataContext())
// {
// UpdateDataHistory(dbContext, true);
// }
// }
// catch (Exception ex)
// {
// Logging.SystemLog.LogException("Disco.BI.JobBI.Statistics.DailyOpenedClosed", ex);
// }
//}
private static void UpdateDataHistory(DiscoDataContext dbContext, bool Refresh = false)
private static void UpdateDataHistory(DiscoDataContext Database, bool Refresh = false)
{
DateTime historyEnd = DateTime.Now.Date;
@@ -98,7 +72,7 @@ namespace Disco.BI.JobBI.Statistics
// Cache Data
while (processDate <= historyEnd)
{
resultData.Add(Data(dbContext, processDate));
resultData.Add(Data(Database, processDate));
processDate = processDate.AddDays(1);
}
_data = resultData;
@@ -127,7 +101,6 @@ namespace Disco.BI.JobBI.Statistics
else
{
DateTime? previousValue = e.GetPreviousPropertyValue<DateTime?>("ClosedDate");
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
if (previousValue.HasValue)
{
@@ -143,33 +116,35 @@ namespace Disco.BI.JobBI.Statistics
affectedStat.TotalJobs += 1;
}
}
}
if (currentValue.HasValue)
DateTime? currentValue = e.GetCurrentPropertyValue<DateTime?>("ClosedDate");
if (currentValue.HasValue)
{
// Add Statistics
// Remove Statistics
var statItem = _data.FirstOrDefault(i => i.Timestamp == currentValue.Value.Date);
if (statItem != null)
{
// Add Statistics
// Remove Statistics
var statItem = _data.FirstOrDefault(i => i.Timestamp == currentValue.Value.Date);
if (statItem != null)
{
statItem.ClosedJobs += 1;
statItem.TotalJobs -= 1;
}
foreach (var affectedStat in _data.Where(i => i.Timestamp > currentValue))
{
affectedStat.TotalJobs -= 1;
}
statItem.ClosedJobs += 1;
statItem.TotalJobs -= 1;
}
foreach (var affectedStat in _data.Where(i => i.Timestamp > currentValue))
{
affectedStat.TotalJobs -= 1;
}
}
}
private static DailyOpenedClosedItem Data(DiscoDataContext dbContext, DateTime ProcessDate)
private static DailyOpenedClosedItem Data(DiscoDataContext Database, DateTime ProcessDate)
{
DateTime processDateStart = ProcessDate;
DateTime processDateEnd = ProcessDate.AddDays(1);
int totalJobs = dbContext.Jobs.Where(j => j.OpenedDate < processDateEnd && (!j.ClosedDate.HasValue || j.ClosedDate > processDateEnd)).Count();
int openedJobs = dbContext.Jobs.Where(j => j.OpenedDate > processDateStart && j.OpenedDate < processDateEnd).Count();
int closedJobs = dbContext.Jobs.Where(j => j.ClosedDate > processDateStart && j.ClosedDate < processDateEnd).Count();
int totalJobs = Database.Jobs.Where(j => j.OpenedDate < processDateEnd && (!j.ClosedDate.HasValue || j.ClosedDate > processDateEnd)).Count();
int openedJobs = Database.Jobs.Where(j => j.OpenedDate > processDateStart && j.OpenedDate < processDateEnd).Count();
int closedJobs = Database.Jobs.Where(j => j.ClosedDate > processDateStart && j.ClosedDate < processDateEnd).Count();
return new DailyOpenedClosedItem()
{
@@ -180,11 +155,11 @@ namespace Disco.BI.JobBI.Statistics
};
}
public static List<DailyOpenedClosedItem> Data(DiscoDataContext dbContext, bool FilterUnimportantWeekends = false)
public static List<DailyOpenedClosedItem> Data(DiscoDataContext Database, bool FilterUnimportantWeekends = false)
{
List<DailyOpenedClosedItem> resultData;
UpdateDataHistory(dbContext);
UpdateDataHistory(Database);
if (FilterUnimportantWeekends)
resultData = _data.Where(i => (i.Timestamp.DayOfWeek != DayOfWeek.Saturday && i.Timestamp.DayOfWeek != DayOfWeek.Sunday) ||
@@ -192,9 +167,6 @@ namespace Disco.BI.JobBI.Statistics
else
resultData = _data.ToList();
// Removed - Live Updated via Repository Monitor; See: RepositoryEvent_JobChange
//resultData.Add(Data(dbContext, DateTime.Today));
return resultData;
}
}
+39 -87
View File
@@ -10,12 +10,12 @@ namespace Disco.BI.JobBI
{
public static class Utilities
{
public static Job Create(DiscoDataContext dbContext, Device device, User user, JobType type, List<JobSubType> subTypes, User initialTech)
public static Job Create(DiscoDataContext Database, Device device, User user, JobType type, List<JobSubType> subTypes, User initialTech, bool addAutoQueues = true)
{
Job j = new Job()
{
JobType = type,
OpenedTechUserId = initialTech.Id,
OpenedTechUserId = initialTech.UserId,
OpenedTechUser = initialTech,
OpenedDate = DateTime.Now
};
@@ -31,26 +31,56 @@ namespace Disco.BI.JobBI
if (user != null)
{
j.User = user;
j.UserId = user.Id;
j.UserId = user.UserId;
}
// Sub Types
List<JobSubType> jobSubTypes = subTypes.ToList();
j.JobSubTypes = jobSubTypes;
dbContext.Jobs.Add(j);
Database.Jobs.Add(j);
// Job Queues
if (addAutoQueues)
{
var queues = from st in subTypes
from jq in st.JobQueues
group st by jq into g
select new { queue = g.Key, subTypes = g };
foreach (var queue in queues)
{
var commentBuilder = new StringBuilder("Automatically added by:").AppendLine();
foreach (var subType in queue.subTypes)
{
commentBuilder.AppendLine().Append("* ").Append(subType.Description);
}
var jqj = new JobQueueJob()
{
JobQueueId = queue.queue.Id,
Job = j,
AddedDate = DateTime.Now,
AddedUserId = initialTech.UserId,
AddedComment = commentBuilder.ToString(),
SLAExpiresDate = queue.queue.DefaultSLAExpiry.HasValue ? (DateTime?)DateTime.Now.AddMinutes(queue.queue.DefaultSLAExpiry.Value) : null,
Priority = JobQueuePriority.Normal
};
Database.JobQueueJobs.Add(jqj);
}
}
switch (type.Id)
{
case JobType.JobTypeIds.HWar:
dbContext.JobMetaWarranties.Add(new JobMetaWarranty() { Job = j });
Database.JobMetaWarranties.Add(new JobMetaWarranty() { Job = j });
break;
case JobType.JobTypeIds.HNWar:
dbContext.JobMetaNonWarranties.Add(new JobMetaNonWarranty() { Job = j });
Database.JobMetaNonWarranties.Add(new JobMetaNonWarranty() { Job = j });
if (device != null)
{
// Add Job Components
var components = dbContext.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var components = Database.DeviceComponents.Include("JobSubTypes").Where(c => !c.DeviceModelId.HasValue || c.DeviceModelId == j.Device.DeviceModelId);
var addedComponents = new List<DeviceComponent>();
foreach (var c in components)
{
@@ -76,10 +106,10 @@ namespace Disco.BI.JobBI
}
}
foreach (var c in addedComponents)
dbContext.JobComponents.Add(new JobComponent()
Database.JobComponents.Add(new JobComponent()
{
Job = j,
TechUserId = initialTech.Id,
TechUserId = initialTech.UserId,
Cost = c.Cost,
Description = c.Description
});
@@ -89,83 +119,5 @@ namespace Disco.BI.JobBI
return j;
}
public static string JobStatusDescription(string StatusId, Job j = null)
{
switch (StatusId)
{
case Job.JobStatusIds.Open:
return "Open";
case Job.JobStatusIds.Closed:
return "Closed";
case Job.JobStatusIds.AwaitingWarrantyRepair:
if (j == null)
return "Awaiting Warranty Repair";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty.ExternalName);
else
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty.ExternalName);
case Job.JobStatusIds.AwaitingRepairs:
if (j == null)
return "Awaiting Repairs";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty.RepairerName);
else
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty.RepairerName);
case Job.JobStatusIds.AwaitingDeviceReturn:
return "Awaiting Device Return";
case Job.JobStatusIds.AwaitingUserAction:
return "Awaiting User Action";
case Job.JobStatusIds.AwaitingAccountingPayment:
return "Awaiting Accounting Payment";
case Job.JobStatusIds.AwaitingAccountingCharge:
return "Awaiting Accounting Charge";
case Job.JobStatusIds.AwaitingInsuranceProcessing:
return "Awaiting Insurance Processing";
default:
return "Unknown";
}
}
public static string JobStatusDescription(string StatusId, JobTableModel.JobTableItemModelIncludeStatus j = null)
{
switch (StatusId)
{
case Job.JobStatusIds.Open:
return "Open";
case Job.JobStatusIds.Closed:
return "Closed";
case Job.JobStatusIds.AwaitingWarrantyRepair:
if (j == null)
return "Awaiting Warranty Repair";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Warranty Repair ({0})", j.JobMetaWarranty_ExternalName);
else
return string.Format("Awaiting Warranty Repair - Not Held ({0})", j.JobMetaWarranty_ExternalName);
case Job.JobStatusIds.AwaitingRepairs:
if (j == null)
return "Awaiting Repairs";
else
if (j.DeviceHeld.HasValue)
return string.Format("Awaiting Repairs ({0})", j.JobMetaNonWarranty_RepairerName);
else
return string.Format("Awaiting Repairs - Not Held ({0})", j.JobMetaNonWarranty_RepairerName);
case Job.JobStatusIds.AwaitingDeviceReturn:
return "Awaiting Device Return";
case Job.JobStatusIds.AwaitingUserAction:
return "Awaiting User Action";
case Job.JobStatusIds.AwaitingAccountingPayment:
return "Awaiting Accounting Payment";
case Job.JobStatusIds.AwaitingAccountingCharge:
return "Awaiting Accounting Charge";
case Job.JobStatusIds.AwaitingInsuranceProcessing:
return "Awaiting Insurance Processing";
default:
return "Unknown";
}
}
}
}
-61
View File
@@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.BI.Search;
using Disco.Models.Repository;
using Disco.Data.Repository;
namespace Disco.BI.UserBI
{
public static class Searching
{
public static List<User> SearchUpstream(string Term)
{
return Interop.ActiveDirectory.ActiveDirectory.SearchUsers(Term).Select(adU => adU.ToRepositoryUser()).ToList();
}
private static List<UserSearchResultItem> Search_SelectUserSearchResultItems(IQueryable<User> Query, int? LimitCount = null)
{
if (LimitCount.HasValue)
Query = Query.Take(LimitCount.Value);
return Query.Select(u => new UserSearchResultItem()
{
Id = u.Id,
Surname = u.Surname,
GivenName = u.GivenName,
DisplayName = u.DisplayName,
AssignedDevicesCount = u.DeviceUserAssignments.Where(dua => !dua.UnassignedDate.HasValue).Count(),
JobCount = u.Jobs.Count()
}).ToList();
}
public static List<UserSearchResultItem> Search(DiscoDataContext dbContext, string Term, int? LimitCount = null)
{
if (string.IsNullOrWhiteSpace(Term) || Term.Length < 2)
throw new ArgumentException("Search Term must contain at least two characters", "Term");
// Search Active Directory & Import Relevant Users
var adImportedUsers = Interop.ActiveDirectory.ActiveDirectory.SearchUsers(Term).Select(adU => adU.ToRepositoryUser());
foreach (var adU in adImportedUsers)
{
var existingUser = dbContext.Users.Find(adU.Id);
if (existingUser != null)
existingUser.UpdateSelf(adU);
else
dbContext.Users.Add(adU);
dbContext.SaveChanges();
UserCache.InvalidateValue(adU.Id);
}
return Search_SelectUserSearchResultItems(dbContext.Users.Where(u =>
u.Id.Contains(Term) ||
u.Surname.Contains(Term) ||
u.GivenName.Contains(Term) ||
u.DisplayName.Contains(Term)
), LimitCount);
}
}
}
-146
View File
@@ -1,146 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using Disco.Models.Repository;
using Disco.Data.Repository;
using System.Web;
using Quartz;
using Quartz.Impl;
using Disco.Services.Tasks;
namespace Disco.BI.UserBI
{
public class UserCache
{
private static ConcurrentDictionary<string, Tuple<User, DateTime>> _Cache = new ConcurrentDictionary<string, Tuple<User, DateTime>>();
private const long CacheTimeoutTicks = 6000000000; // 10 Minutes
private const string CacheHttpRequestKey = "Disco_CurrentUser";
public static User CurrentUser
{
get
{
string username = null;
User user;
// Check for ASP.NET
if (HttpContext.Current != null)
{
if (HttpContext.Current.Request.IsAuthenticated)
{
user = (User)HttpContext.Current.Items[CacheHttpRequestKey];
if (user != null)
return user;
username = HttpContext.Current.User.Identity.Name;
}
else
{
return null;
//throw new PlatformNotSupportedException("ASP.NET Authentication is not correctly configured");
}
}
// User default User
if (username == null)
{
username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
user = GetUser(username);
if (HttpContext.Current != null && HttpContext.Current.Request.IsAuthenticated)
{
// Cache in current request
HttpContext.Current.Items[CacheHttpRequestKey] = user;
}
return user;
}
}
public static User GetUser(string Username)
{
// Check Cache
User u = TryUserCache(Username);
if (u == null)
{
// Load from Repository
using (DiscoDataContext dbContext = new DiscoDataContext())
{
u = GetUser(Username, dbContext, true);
}
}
return u;
}
public static User GetUser(string Username, DiscoDataContext dbContext, bool ForceRefresh = false)
{
User u = null;
// Check Cache
if (!ForceRefresh)
u = TryUserCache(Username);
if (u == null)
{
string username = Username.ToLower();
u = UserBI.Utilities.LoadUser(dbContext, username);
SetValue(username, u);
}
return u;
}
private static User TryUserCache(string Username)
{
string username = Username.ToLower();
Tuple<User, DateTime> userRecord;
if (_Cache.TryGetValue(username, out userRecord))
{
if (userRecord.Item2 > DateTime.Now)
return userRecord.Item1;
else
_Cache.TryRemove(username, out userRecord);
}
return null;
}
public static bool InvalidateValue(string Key)
{
Tuple<User, DateTime> userRecord;
return _Cache.TryRemove(Key.ToLower(), out userRecord);
}
private static bool SetValue(string Key, User User)
{
string key = Key.ToLower();
Tuple<User, DateTime> userRecord = new Tuple<User, DateTime>(User, DateTime.Now.AddTicks(CacheTimeoutTicks));
if (_Cache.ContainsKey(key))
{
Tuple<User, DateTime> oldUser;
if (_Cache.TryGetValue(key, out oldUser))
{
return _Cache.TryUpdate(key, userRecord, oldUser);
}
}
return _Cache.TryAdd(key, userRecord);
}
internal static void CleanStaleCache()
{
var usernames = _Cache.Keys.ToArray();
foreach (string username in usernames)
{
Tuple<User, DateTime> userRecord;
if (_Cache.TryGetValue(username, out userRecord))
{
if (userRecord.Item2 <= DateTime.Now)
_Cache.TryRemove(username, out userRecord);
}
}
}
}
}
-76
View File
@@ -1,76 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Disco.Models.Repository;
using Disco.Data.Repository;
using Disco.Models.BI.Search;
using System.Runtime.InteropServices;
using System.DirectoryServices.ActiveDirectory;
using Disco.Services.Logging;
namespace Disco.BI.UserBI
{
public static class Utilities
{
public static User LoadUser(DiscoDataContext dbContext, string Username)
{
// Machine Account ?
if (Username.EndsWith("$"))
{
return Interop.ActiveDirectory.ActiveDirectory.GetMachineAccount(Username).ToRepositoryUser();
}
// User Account
User user = null;
try
{
var ADUser = Interop.ActiveDirectory.ActiveDirectory.GetUserAccount(Username);
if (ADUser == null)
throw new ArgumentException(string.Format("Invalid Username: '{0}'", Username), "Username");
user = ADUser.ToRepositoryUser();
}
catch (COMException ex)
{
// If "Server is not operational" then Try Cache
if (ex.ErrorCode != -2147016646)
{
throw ex;
}
SystemLog.LogException("Primary Domain Controller Down? Disco.BI.UserBI.Utilities.LoadUser", ex);
}
catch (ActiveDirectoryOperationException ex)
{
// Try From Cache...
SystemLog.LogException("Primary Domain Controller Down? Disco.BI.UserBI.Utilities.LoadUser", ex);
}
// Update Repository
User existingUser;
if (user == null)
{
string username = Username.Contains(@"\") ? Username.Substring(Username.IndexOf(@"\") + 1) : Username;
existingUser = dbContext.Users.Find(username);
if (existingUser == null)
throw new ArgumentException(string.Format("Invalid User - Not In Disco DB: '{0}'", Username), "Username");
else
return existingUser;
}
existingUser = dbContext.Users.Find(user.Id);
if (existingUser == null)
{
dbContext.Users.Add(user);
}
else
{
existingUser.UpdateSelf(user);
user = existingUser;
}
dbContext.SaveChanges();
return user;
}
}
}
@@ -1,83 +0,0 @@
using Disco.BI.Wireless.eduSTAR;
using Disco.Data.Configuration;
using Disco.Data.Repository;
using Disco.BI.Extensions;
using Disco.Models.Repository;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Disco.BI.Wireless
{
public abstract class BaseWirelessProvider
{
protected DiscoDataContext dbContext;
private static object _CertificateAllocateLock = System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(new object());
public static BaseWirelessProvider GetProvider(DiscoDataContext dbContext)
{
string provider = dbContext.DiscoConfiguration.Wireless.Provider;
if (provider == "eduSTAR")
{
return new eduSTARWirelessProvider(dbContext);
}
throw new System.NotSupportedException(string.Format("Wireless Provider Not Supported: '{0}'", dbContext.DiscoConfiguration.Wireless.Provider));
}
protected BaseWirelessProvider(DiscoDataContext dbContext)
{
this.dbContext = dbContext;
}
private DeviceCertificate CertificateAllocate(ref Device repoDevice)
{
lock (BaseWirelessProvider._CertificateAllocateLock)
{
this.FillCertificateAutoBuffer();
int timeout = 60;
int freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
while (!(freeCertCount > 0 | timeout <= 0))
{
System.Threading.Thread.Sleep(500);
freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
timeout--;
}
DeviceCertificate cert = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).FirstOrDefault();
if (cert == null)
{
WirelessCertificatesLog.LogAllocationFailed(repoDevice.SerialNumber);
throw new System.InvalidOperationException("Unable to Allocate a Wireless Certificate");
}
WirelessCertificatesLog.LogAllocated(cert.Name, repoDevice.SerialNumber);
cert.DeviceSerialNumber = repoDevice.SerialNumber;
cert.AllocatedDate = System.DateTime.Now;
this.dbContext.SaveChanges();
return cert;
}
}
public DeviceCertificate Enrol(Device repoDevice)
{
DeviceCertificate allocatedCert = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == repoDevice.SerialNumber && c.Enabled).FirstOrDefault();
if (allocatedCert != null)
{
return allocatedCert;
}
// Removed 2012-06-14 G# - Properties moved to DeviceProfile model & DB Migrated in DBv3.
//if (repoDevice.DeviceProfile.Configuration(this.dbContext).AllocateWirelessCertificate)
if (repoDevice.DeviceProfile.AllocateCertificate)
{
allocatedCert = this.CertificateAllocate(ref repoDevice);
return allocatedCert;
}
else
{
return null;
}
}
protected abstract void FillCertificateAutoBuffer();
public abstract void FillCertificateBuffer(int Amount);
public abstract System.Collections.Generic.List<string> RemoveExistingCertificateNames();
}
}
@@ -1,304 +0,0 @@
using Disco.Logging;
using Disco.Logging.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Disco.BI.Wireless
{
public class WirelessCertificatesLog : LogBase
{
public enum EventTypeIds
{
RetrievalStarting = 10,
RetrievalProgress,
RetrievalFinished,
RetrievalWarning = 15,
RetrievalError,
RetrievalCertificateStarting = 20,
RetrievalCertificateFinished = 22,
RetrievalCertificateWarning = 25,
RetrievalCertificateError,
Allocated = 40,
AllocationFailed = 50
}
private const int _ModuleId = 60;
private static bool _IsCertificateRetrievalProcessing;
private static string _CertificateRetrievalStatus;
private static int _CertificateRetrievalProgress;
public static WirelessCertificatesLog Current
{
get
{
return (WirelessCertificatesLog)LogContext.LogModules[60];
}
}
public static bool IsCertificateRetrievalProcessing
{
get
{
return WirelessCertificatesLog._IsCertificateRetrievalProcessing;
}
}
public override string ModuleDescription
{
get
{
return "Wireless Certificates";
}
}
public override int ModuleId
{
get
{
return 60;
}
}
public override string ModuleName
{
get
{
return "WirelessCertificates";
}
}
[System.Diagnostics.DebuggerNonUserCode]
public WirelessCertificatesLog()
{
}
private static void Log(WirelessCertificatesLog.EventTypeIds EventTypeId, params object[] Args)
{
WirelessCertificatesLog.Current.Log((int)EventTypeId, Args);
}
public static void LogRetrievalStarting(int CertificateCount, int CertificateIdFrom, int CertificateIdTo)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalStarting, new object[]
{
CertificateCount,
CertificateIdFrom,
CertificateIdTo
});
}
public static void LogRetrievalFinished()
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalFinished, new object[0]);
}
public static void LogRetrievalWarning(string Message)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalWarning, new object[]
{
Message
});
}
public static void LogRetrievalError(string Message)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalError, new object[]
{
Message
});
}
public static void LogRetrievalCertificateStarting(string CertificateId)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateStarting, new object[]
{
CertificateId
});
}
public static void LogRetrievalCertificateFinished(string CertificateId)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateFinished, new object[]
{
CertificateId
});
}
public static void LogRetrievalCertificateWarning(string CertificateId, string Message)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateWarning, new object[]
{
CertificateId,
Message
});
}
public static void LogRetrievalCertificateError(string CertificateId, string Message)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalCertificateError, new object[]
{
CertificateId,
Message
});
}
public static void LogAllocated(string CertificateId, string DeviceSerialNumber)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.Allocated, new object[]
{
CertificateId,
DeviceSerialNumber
});
}
public static void LogAllocationFailed(string DeviceSerialNumber)
{
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.AllocationFailed, new object[]
{
DeviceSerialNumber
});
}
public static void LogCertificateRetrievalProgress(bool? IsProcessing, int? Progress, string Status)
{
bool flag = IsProcessing.HasValue;
if (flag)
{
WirelessCertificatesLog._IsCertificateRetrievalProcessing = IsProcessing.Value;
}
flag = WirelessCertificatesLog._IsCertificateRetrievalProcessing;
if (flag)
{
bool flag2 = Status != null;
if (flag2)
{
WirelessCertificatesLog._CertificateRetrievalStatus = Status;
}
flag2 = Progress.HasValue;
if (flag2)
{
WirelessCertificatesLog._CertificateRetrievalProgress = Progress.Value;
}
}
else
{
WirelessCertificatesLog._CertificateRetrievalStatus = null;
WirelessCertificatesLog._CertificateRetrievalProgress = 0;
}
WirelessCertificatesLog.Log(WirelessCertificatesLog.EventTypeIds.RetrievalProgress, new object[]
{
WirelessCertificatesLog._IsCertificateRetrievalProcessing,
WirelessCertificatesLog._CertificateRetrievalProgress,
WirelessCertificatesLog._CertificateRetrievalStatus
});
}
protected override System.Collections.Generic.List<LogEventType> LoadEventTypes()
{
return new System.Collections.Generic.List<LogEventType>
{
new LogEventType
{
Id = 10,
ModuleId = 60,
Name = "Retrieval Starting",
Format = "Starting retrieval of {0} certificate/s ({1} to {2})",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 11,
ModuleId = 60,
Name = "Retrieval Progress",
Format = "Processing: {0}; {1}% Complete; Status: {2}",
Severity = 0,
UseLive = true,
UsePersist = false,
UseDisplay = false
},
new LogEventType
{
Id = 12,
ModuleId = 60,
Name = "Retrieval Finished",
Format = "Retrieval of Certificates Complete",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 15,
ModuleId = 60,
Name = "Retrieval Warning",
Format = "Retrieval Warning: {0}",
Severity = 1,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 16,
ModuleId = 60,
Name = "Retrieval Error",
Format = "Retrieval Error: {0}",
Severity = 2,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 20,
ModuleId = 60,
Name = "Retrieval Certificate Starting",
Format = "Retrieving Certificate: {0}",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 22,
ModuleId = 60,
Name = "Retrieval Certificate Finished",
Format = "Certificate Retrieved: {0}",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 25,
ModuleId = 60,
Name = "Retrieval Certificate Warning",
Format = "{0} Certificate Warning: {1}",
Severity = 1,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 26,
ModuleId = 60,
Name = "Retrieval Certificate Error",
Format = "{0} Certificate Error: {1}",
Severity = 2,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 40,
ModuleId = 60,
Name = "Allocated",
Format = "Certificate {0} allocated to {1}",
Severity = 0,
UseLive = true,
UsePersist = true,
UseDisplay = true
},
new LogEventType
{
Id = 50,
ModuleId = 60,
Name = "Allocation Failed",
Format = "No certificates available for Device: {0}",
Severity = 2,
UseLive = true,
UsePersist = true,
UseDisplay = true
}
};
}
}
}
@@ -1,283 +0,0 @@
using Disco.BI.Wireless.eduSTAR.eduSTARWirelessCertService;
using Disco.Data.Repository;
using Disco.Models.Repository;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;
namespace Disco.BI.Wireless.eduSTAR
{
public class eduSTARWirelessProvider : BaseWirelessProvider
{
private class BulkLoadCertificatesContract
{
public int Start { get; set; }
public int Count { get; set; }
}
private static object _BulkLoadThreadLock = new object();
private static System.Threading.Thread _BulkLoadThread;
public eduSTARWirelessProvider(DiscoDataContext dbContext)
: base(dbContext)
{
}
protected override void FillCertificateAutoBuffer()
{
int freeCertCount = this.dbContext.DeviceCertificates.Where(c => c.DeviceSerialNumber == null && c.Enabled).Count();
if (freeCertCount <= this.dbContext.DiscoConfiguration.Wireless.CertificateAutoBufferLow)
{
this.BulkLoadCertificates(0);
}
}
public override void FillCertificateBuffer(int Amount)
{
this.BulkLoadCertificates(Amount);
}
public override System.Collections.Generic.List<string> RemoveExistingCertificateNames()
{
return new System.Collections.Generic.List<string>
{
"(eduPaSS)",
"(CN=Computers, ?DC=services, ?DC=education, ?DC=vic, ?DC=gov, ?DC=au)"
};
}
private void BulkLoadCertificates(int Amount = 0)
{
if (eduSTARWirelessProvider._BulkLoadThread == null)
{
lock (eduSTARWirelessProvider._BulkLoadThreadLock)
{
if (eduSTARWirelessProvider._BulkLoadThread == null)
{
int start = 0;
if (this.dbContext.DeviceCertificates.Count() > 0)
{
start = this.dbContext.DeviceCertificates.Max(c => c.ProviderIndex) + 1;
}
int buffer = this.dbContext.DeviceCertificates.Count(c => c.DeviceSerialNumber == null && c.Enabled);
int count = this.dbContext.DiscoConfiguration.Wireless.CertificateAutoBufferMax - buffer;
if (Amount > 0)
{
count = Amount;
}
if (count > 0)
{
eduSTARWirelessProvider.BulkLoadCertificatesContract contract = new eduSTARWirelessProvider.BulkLoadCertificatesContract
{
Start = start,
Count = count
};
System.Threading.ParameterizedThreadStart threadStart = delegate(object a0)
{
this.BulkLoadCertificatesStart((eduSTARWirelessProvider.BulkLoadCertificatesContract)a0);
}
;
eduSTARWirelessProvider._BulkLoadThread = new System.Threading.Thread(threadStart);
eduSTARWirelessProvider._BulkLoadThread.Start(contract);
}
}
}
}
}
private void BulkLoadCertificatesStart(eduSTARWirelessProvider.BulkLoadCertificatesContract contract)
{
try
{
WirelessCertificatesLog.LogRetrievalStarting(contract.Count, contract.Start, contract.Start + contract.Count - 1);
WirelessCertificatesLog.LogCertificateRetrievalProgress(true, 0, string.Format("Starting Bulk Retrieval (Loading {0} Certificate/s)", contract.Count));
DiscoDataContext dbLocalContext = new DiscoDataContext();
try
{
WirelessCertServiceSoapClient proxy = this.GetProxy();
try
{
int num = contract.Start + contract.Count - 1;
int index = contract.Start;
while (true)
{
int num2 = num;
if (index > num2)
{
break;
}
WirelessCertificatesLog.LogCertificateRetrievalProgress(true, (int)System.Math.Round(unchecked(((double)checked(index - contract.Start) + 0.5) / (double)contract.Count * 100.0)), string.Format("Retrieving Certificate {0} of {1}", index - contract.Start + 1, contract.Count));
DeviceCertificate cert = this.LoadCertificate(index, proxy, dbLocalContext);
dbLocalContext.DeviceCertificates.Add(cert);
dbLocalContext.SaveChanges();
WirelessCertificatesLog.LogRetrievalCertificateFinished(cert.Name);
index++;
}
}
finally
{
bool flag = proxy != null;
if (flag)
{
((System.IDisposable)proxy).Dispose();
}
}
}
finally
{
bool flag = dbLocalContext != null;
if (flag)
{
((System.IDisposable)dbLocalContext).Dispose();
}
}
}
catch (System.Exception ex)
{
WirelessCertificatesLog.LogRetrievalError(string.Format("[{0}] {1}", ex.GetType().Name, ex.Message));
throw ex;
}
finally
{
lock (eduSTARWirelessProvider._BulkLoadThreadLock)
{
eduSTARWirelessProvider._BulkLoadThread = null;
}
WirelessCertificatesLog.LogRetrievalFinished();
WirelessCertificatesLog.LogCertificateRetrievalProgress(false, null, null);
}
}
private DeviceCertificate LoadCertificate(int Index, DiscoDataContext dbContext)
{
DeviceCertificate LoadCertificate;
try
{
WirelessCertServiceSoapClient proxy = this.GetProxy();
try
{
LoadCertificate = this.LoadCertificate(Index, proxy, dbContext);
}
finally
{
bool flag = proxy != null;
if (flag)
{
((System.IDisposable)proxy).Dispose();
}
}
}
catch (System.Exception ex)
{
WirelessCertificatesLog.LogRetrievalCertificateError(Index.ToString(), string.Format("[{0}] {1}", ex.GetType().Name, ex.Message));
throw ex;
}
return LoadCertificate;
}
private DeviceCertificate LoadCertificate(int Index, WirelessCertServiceSoapClient Proxy, DiscoDataContext dbContext)
{
bool flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId);
if (flag)
{
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount SchoolId");
}
flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountUsername);
if (flag)
{
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount Username");
}
flag = string.IsNullOrWhiteSpace(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountPassword);
if (flag)
{
throw new System.ArgumentException("Wireless Certificates: Invalid ServiceAccount Password");
}
DeviceCertificate cert = new DeviceCertificate
{
ProviderIndex = Index,
Name = string.Format("{0}-{1}", dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId, Index.ToString("00000")),
Enabled = true
};
WirelessCertificatesLog.LogRetrievalCertificateStarting(cert.Name);
string response;
try
{
response = Proxy.GetWirelessCert(dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountSchoolId, cert.Name, "password", dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountUsername, dbContext.DiscoConfiguration.Wireless.eduSTAR_ServiceAccountPassword);
}
catch (System.Exception ex)
{
WirelessCertificatesLog.LogRetrievalCertificateError(cert.Name, ex.Message);
throw ex;
}
try
{
byte[] responseBytes = System.Convert.FromBase64String(response);
System.IO.MemoryStream responseByteStream = new System.IO.MemoryStream(responseBytes);
try
{
ZipFile responseZip = ZipFile.Read(responseByteStream);
ZipEntry certFile = responseZip.FirstOrDefault((ZipEntry ze) => ze.FileName.EndsWith(".pfx", System.StringComparison.InvariantCultureIgnoreCase));
System.IO.MemoryStream certByteStream = new System.IO.MemoryStream();
try
{
certFile.Extract(certByteStream);
cert.Content = certByteStream.ToArray();
}
finally
{
flag = (certByteStream != null);
if (flag)
{
((System.IDisposable)certByteStream).Dispose();
}
}
}
finally
{
flag = (responseByteStream != null);
if (flag)
{
((System.IDisposable)responseByteStream).Dispose();
}
}
}
catch (System.Exception ex2)
{
if (response.Contains("Computer with this name already exists"))
{
WirelessCertificatesLog.LogRetrievalCertificateWarning(cert.Name, "Already exists on eduSTAR server, disabling and skipping.");
cert.ExpirationDate = System.DateTime.Now;
cert.Enabled = false;
cert.Content = null;
return cert;
}
throw new System.InvalidOperationException(string.Format("Unable to Uncompress (Server returned: {0})", response), ex2);
}
try
{
X509Certificate2 x509Cert = new X509Certificate2(cert.Content, "password");
cert.ExpirationDate = x509Cert.NotAfter;
}
catch (System.Exception ex3)
{
throw new System.InvalidOperationException("Invalid Certificate returned by Server", ex3);
}
return cert;
}
private WirelessCertServiceSoapClient GetProxy()
{
BasicHttpBinding binding = new BasicHttpBinding();
// Don't Use Proxy
binding.UseDefaultWebProxy = false;
binding.ProxyAddress = null;
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.MaxReceivedMessageSize = 524288L;
binding.ReaderQuotas.MaxStringContentLength = 524288;
EndpointAddress endpointAddress = new EndpointAddress(new Uri("https://www.eduweb.vic.gov.au/edustar/WirelessCertWS/wirelesscertws.asmx"), new AddressHeader[0]);
return new WirelessCertServiceSoapClient(binding, endpointAddress);
}
}
}
+18 -67
View File
@@ -46,35 +46,6 @@
<Reference Include="itextsharp">
<HintPath>..\Resources\Libraries\iTextSharp\itextsharp.dll</HintPath>
</Reference>
<Reference Include="LumenWorks.Framework.IO">
<HintPath>..\..\..\Resources\Libraries\LumenWorks.Framework.IO\LumenWorks.Framework.IO.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.2\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Owin, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Owin.1.1.2\lib\net45\Microsoft.AspNet.SignalR.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.SystemWeb, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.SystemWeb.1.1.2\lib\net45\Microsoft.AspNet.SignalR.SystemWeb.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Host.SystemWeb">
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.1.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.5\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="Quartz">
<HintPath>..\Resources\Libraries\Quartz\Quartz.dll</HintPath>
</Reference>
@@ -88,20 +59,21 @@
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Reactive.Core, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Core, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
<HintPath>..\packages\Rx-Core.2.2.4\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Interfaces, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll</HintPath>
<HintPath>..\packages\Rx-Interfaces.2.2.4\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.1.30214.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Reactive.Linq, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll</HintPath>
<HintPath>..\packages\Rx-Linq.2.2.4\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices">
<HintPath>..\packages\Rx-PlatformServices.2.1.30214.0\lib\Net45\System.Reactive.PlatformServices.dll</HintPath>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Rx-PlatformServices.2.2.4\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
@@ -123,13 +95,12 @@
<Compile Include="BI\AttachmentBI\Utilities.cs" />
<Compile Include="BI\DeviceBI\BatchUtilities.cs" />
<Compile Include="BI\DeviceBI\DeviceModelBI.cs" />
<Compile Include="BI\DeviceBI\Importing\Export.cs" />
<Compile Include="BI\DeviceBI\Importing\Import.cs" />
<Compile Include="BI\DeviceBI\Importing\ImportParseTask.cs" />
<Compile Include="BI\DeviceBI\Importing\ImportProcessTask.cs" />
<Compile Include="BI\DeviceBI\Searching.cs" />
<Compile Include="BI\DeviceBI\Migration\LogMacAddressImporting.cs" />
<Compile Include="BI\DisposableImageCollection.cs" />
<Compile Include="BI\DocumentTemplateBI\DocumentTemplateQRCodeLocationCache.cs" />
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateUsersManagedGroup.cs" />
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateDevicesManagedGroup.cs" />
<Compile Include="BI\DocumentTemplateBI\ManagedGroups\DocumentTemplateManagedGroups.cs" />
<Compile Include="BI\Expressions\EvaluateExpressionParseException.cs" />
<Compile Include="BI\Expressions\ExpressionCachePreloadTask.cs" />
<Compile Include="BI\Expressions\Extensions\DataExt.cs" />
@@ -142,16 +113,19 @@
<Compile Include="BI\Expressions\Extensions\UserExt.cs" />
<Compile Include="BI\Extensions\AttachmentActionExtensions.cs" />
<Compile Include="BI\Extensions\AttachmentExtensions.cs" />
<Compile Include="BI\Extensions\AuthorizationRoleExtensions.cs" />
<Compile Include="BI\Extensions\ClientServicesExtensions.cs" />
<Compile Include="BI\Extensions\UserFlagActionExtensions.cs" />
<Compile Include="BI\Extensions\DeviceActionExtensions.cs" />
<Compile Include="BI\Extensions\DeviceBatchExtensions.cs" />
<Compile Include="BI\Extensions\DeviceCertificateExtensions.cs" />
<Compile Include="BI\Extensions\DeviceDetailExtensions.cs" />
<Compile Include="BI\Extensions\DeviceModelExtensions.cs" />
<Compile Include="BI\Extensions\DeviceProfileExtensions.cs" />
<Compile Include="BI\Extensions\JobActionExtensions.cs" />
<Compile Include="BI\Extensions\JobExtensions.cs" />
<Compile Include="BI\Extensions\JobFlagExtensions.cs" />
<Compile Include="BI\Extensions\JobTableExtensions.cs" />
<Compile Include="BI\Extensions\JobQueueActionExtensions.cs" />
<Compile Include="BI\Extensions\UserExtensions.cs" />
<Compile Include="BI\Extensions\WirelessCertificateExtensions.cs" />
<Compile Include="BI\Extensions\DeviceExtensions.cs" />
@@ -171,37 +145,14 @@
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterJob.cs" />
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterCleanCacheJob.cs" />
<Compile Include="BI\DocumentTemplateBI\Importer\DocumentImporterLog.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectory.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryCachedGroups.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryHelpers.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryMachineAccountExtensions.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryOrganisationalUnit.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUpdateLastNetworkLogonDateJob.cs" />
<Compile Include="BI\Interop\ActiveDirectory\ActiveDirectoryUserAccountExtensions.cs" />
<Compile Include="BI\Expressions\ExpressionCache.cs" />
<Compile Include="BI\Interop\Community\UpdateCheck.cs" />
<Compile Include="BI\Interop\Community\UpdateCheckTask.cs" />
<Compile Include="BI\Interop\MimeTypes.cs" />
<Compile Include="BI\Interop\Pdf\PdfGenerator.cs" />
<Compile Include="BI\Interop\Pdf\PdfImporter.cs" />
<Compile Include="BI\Interop\PluginServices\IDiscoScheduledTask.cs" />
<Compile Include="BI\Interop\PluginServices\Utilities.cs" />
<Compile Include="BI\Interop\SignalRHandlers\AdminAuthorizedPersistentConnection.cs" />
<Compile Include="BI\Interop\SignalRHandlers\AuthorizedPersistentConnection.cs" />
<Compile Include="BI\Interop\SignalRHandlers\HeldDeviceNotifications.cs" />
<Compile Include="BI\Interop\SignalRHandlers\LogNotifications.cs" />
<Compile Include="BI\Interop\SignalRHandlers\RepositoryMonitorNotifications.cs" />
<Compile Include="BI\Interop\SignalRHandlers\ScheduledTasksStatusNotifications.cs" />
<Compile Include="BI\Interop\SignalRHandlers\SignalRAuthenticationWorkaround.cs" />
<Compile Include="BI\Interop\SignalRHandlers\UserHeldDeviceNotifications.cs" />
<Compile Include="BI\JobBI\ManagedJobList.cs" />
<Compile Include="BI\JobBI\Searching.cs" />
<Compile Include="BI\JobBI\Statistics\DailyOpenedClosed.cs" />
<Compile Include="BI\JobBI\Utilities.cs" />
<Compile Include="BI\UserBI\Searching.cs" />
<Compile Include="BI\UserBI\UserCache.cs" />
<Compile Include="BI\UserBI\UserCachePruneTask.cs" />
<Compile Include="BI\UserBI\Utilities.cs" />
<Compile Include="BI\Extensions\UtilityExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
@@ -256,7 +207,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_StartDate="2011/7/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
</VisualStudio>
</ProjectExtensions>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0725.2249")]
[assembly: AssemblyFileVersion("1.2.0725.2249")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
+24
View File
@@ -18,4 +18,28 @@
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+5 -12
View File
@@ -1,16 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.SignalR.Core" version="1.1.2" targetFramework="net45" />
<package id="Microsoft.AspNet.SignalR.Owin" version="1.1.2" targetFramework="net45" />
<package id="Microsoft.AspNet.SignalR.SystemWeb" version="1.1.2" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="1.0.1" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
<package id="Newtonsoft.Json" version="5.0.5" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Rx-Core" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Linq" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Main" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Core" version="2.2.4" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.4" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.4" targetFramework="net45" />
<package id="Rx-Main" version="2.2.4" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.4" targetFramework="net45" />
</packages>
+3 -4
View File
@@ -48,9 +48,8 @@
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.5\lib\net40\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -122,7 +121,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_BuildAction="Both" BuildVersion_StartDate="2011/7/1" BuildVersion_DetectChanges="False" BuildVersion_UseGlobalSettings="False" />
<UserProperties BuildVersion_UseGlobalSettings="False" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2014/6/1" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" />
</VisualStudio>
</ProjectExtensions>
<PropertyGroup>
+8 -5
View File
@@ -26,6 +26,7 @@ namespace Disco.Client.Extensions
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
enrol.DeviceDNSDomainName = Interop.SystemAudit.DeviceDNSDomainName;
// LAN
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
@@ -43,7 +44,7 @@ namespace Disco.Client.Extensions
throw new ClientServiceException("Enrolment", "Server denied enrolment (Empty Response)");
ErrorReporting.EnrolmentSessionId = enrolResponse.SessionId;
if (!string.IsNullOrEmpty(enrolResponse.ErrorMessage))
throw new ClientServiceException("Enrolment", enrolResponse.ErrorMessage);
@@ -102,7 +103,8 @@ namespace Disco.Client.Extensions
// Flush Logged-On History
if (!string.IsNullOrEmpty(enrolResponse.DeviceDomainName))
{
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true)){
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
{
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceDomainName, RegistryValueKind.String);
regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String);
}
@@ -130,9 +132,10 @@ namespace Disco.Client.Extensions
// Only run task if Assigned User was specified
if (!string.IsNullOrWhiteSpace(enrolResponse.DeviceAssignedUserSID))
{
Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring permissions for the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000);
Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000);
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain);
if (enrolResponse.DeviceAssignedUserIsLocalAdmin)
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain);
// Make Windows think this user was the last to logon
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
@@ -183,6 +186,6 @@ namespace Disco.Client.Extensions
Interop.Certificates.AddCertificate(StoreName.My, StoreLocation.LocalMachine, certPersonal);
}
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 32 KiB

+2 -2
View File
@@ -22,8 +22,8 @@ namespace Disco.Client.Interop
using (DirectoryEntry member = new DirectoryEntry(memberRef))
{
var memberPath = member.Path;
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.InvariantCultureIgnoreCase) ||
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.InvariantCultureIgnoreCase))
if (memberPath.Equals(string.Format("WinNT://{0}/{1}", UserDomain, Username), StringComparison.OrdinalIgnoreCase) ||
memberPath.Equals(string.Format("WinNT://{0}", UserSID), StringComparison.OrdinalIgnoreCase))
return false;
}
}
+11 -3
View File
@@ -13,7 +13,7 @@ namespace Disco.Client.Interop
private static NetworkAdapterInfo PrimaryLanNetworkAdapter { get; set; }
private static NetworkAdapterInfo PrimaryWlanNetworkAdapter { get; set; }
static Network()
public static void Initialize()
{
// Get All Adapters
RetrieveLanAdapters();
@@ -21,12 +21,20 @@ namespace Disco.Client.Interop
if (NetworkAdapters.Count > 0)
{
// Only Retrieve Wlan Adapters if at least one adapter was found by WMI
RetrieveWlanAdapters();
try
{
RetrieveWlanAdapters();
}
catch (DllNotFoundException)
{
// Ignore DllNotFoundException
// This which indicates 'Wlanapi.dll' isn't present (eg. Windows Servers)
}
// Determine Primary Adapters
// Lan
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.InvariantCultureIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault();
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter && n.NetConnectionId.StartsWith("Local Area Connection", StringComparison.OrdinalIgnoreCase)).OrderByDescending(n => n.Speed).FirstOrDefault();
// Might be too restrictive - remove name restriction just in case.
if (PrimaryLanNetworkAdapter == null)
PrimaryLanNetworkAdapter = NetworkAdapters.Where(n => !n.IsWLanAdapter).OrderByDescending(n => n.Speed).FirstOrDefault();
+8 -5
View File
@@ -17,8 +17,9 @@ namespace Disco.Client.Interop
public static string DeviceType { get; private set; }
public static string DeviceUUID { get; private set; }
public static bool DeviceIsPartOfDomain { get; private set; }
public static string DeviceDNSDomainName { get; private set; }
static SystemAudit()
public static void Initialize()
{
// Get BIOS Information
try
@@ -56,7 +57,7 @@ namespace Disco.Client.Interop
// Get System Information
try
{
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType FROM Win32_ComputerSystem"))
using (ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("SELECT Manufacturer, Model, PartOfDomain, PCSystemType, Domain FROM Win32_ComputerSystem"))
{
using (ManagementObjectCollection mResults = mSearcher.Get())
{
@@ -74,6 +75,8 @@ namespace Disco.Client.Interop
DeviceIsPartOfDomain = (bool)mItem.GetPropertyValue("PartOfDomain");
DeviceType = PCSystemTypeToString((UInt16)mItem.GetPropertyValue("PCSystemType"));
DeviceDNSDomainName = DeviceIsPartOfDomain ? mItem.GetPropertyValue("Domain") as string : null;
}
else
{
@@ -124,9 +127,9 @@ namespace Disco.Client.Interop
// Added 2012-11-22 G# - Lenovo IdeaPad Serial SHIM
// http://www.discoict.com.au/forum/feature-requests/2012/11/serial-number-detection-on-ideapads.aspx
if (string.IsNullOrWhiteSpace(DeviceSerialNumber) ||
(DeviceManufacturer.Equals("LENOVO", StringComparison.InvariantCultureIgnoreCase) &&
(DeviceModel.Equals("S10-3", StringComparison.InvariantCultureIgnoreCase) // S10-3
|| DeviceModel.Equals("2957", StringComparison.InvariantCultureIgnoreCase)))) // S10-2
(DeviceManufacturer.Equals("LENOVO", StringComparison.OrdinalIgnoreCase) &&
(DeviceModel.Equals("S10-3", StringComparison.OrdinalIgnoreCase) // S10-3
|| DeviceModel.Equals("2957", StringComparison.OrdinalIgnoreCase)))) // S10-2
{
try
{
+5 -1
View File
@@ -44,7 +44,7 @@ namespace Disco.Client
// Ignore Local Proxies
WebRequest.DefaultWebProxy = new WebProxy();
// Override Http 100 Continue Behavour
// Override Http 100 Continue Behaviour
ServicePointManager.Expect100Continue = false;
// Assume success unless otherwise notified
@@ -59,6 +59,10 @@ namespace Disco.Client
{
Presentation.DelayUI = true; // Add Delays on Error
}
// Initialize Interop
Interop.SystemAudit.Initialize();
Interop.Network.Initialize();
}
public static bool WhoAmI()
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0725.2102")]
[assembly: AssemblyFileVersion("1.2.0725.2102")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="5.0.5" targetFramework="net40-Client" />
<package id="Newtonsoft.Json" version="6.0.3" targetFramework="net40-Client" />
</packages>
+4 -2
View File
@@ -149,8 +149,10 @@ namespace Disco.ClientBootstrapper
// Unzip Client
statusUI.UpdateStatus(null, "Extracting", "Retrieving Preparation Client, Please wait...", true, -1);
string clientLocation = Path.Combine(tempWorkingDirectory, "PreparationClient");
if (!Directory.Exists(clientLocation))
Directory.CreateDirectory(clientLocation);
if (Directory.Exists(clientLocation))
Directory.Delete(clientLocation, true);
Directory.CreateDirectory(clientLocation);
using (var clientSource = Ionic.Zip.ZipFile.Read(clientSourceLocation))
{
clientSource.ExtractAll(clientLocation, Ionic.Zip.ExtractExistingFileAction.OverwriteSilently);
@@ -319,7 +319,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" BuildVersion_BuildAction="Both" BuildVersion_UseGlobalSettings="False" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_DetectChanges="False" BuildVersion_StartDate="2011/7/1" />
<UserProperties BuildVersion_StartDate="2014/6/1" BuildVersion_DetectChanges="False" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.DeltaBaseYear.MonthAndDayStamp.TimeStamp" />
</VisualStudio>
</ProjectExtensions>
<PropertyGroup>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 32 KiB

@@ -74,14 +74,14 @@ namespace Disco.ClientBootstrapper.Interop
// Only Copy Certain Files
// Copy Wireless Certificates
if (fileName.StartsWith("WLAN_Cert_Root_", StringComparison.InvariantCultureIgnoreCase) ||
fileName.StartsWith("WLAN_Cert_Intermediate_", StringComparison.InvariantCultureIgnoreCase) ||
fileName.StartsWith("WLAN_Cert_Personal_", StringComparison.InvariantCultureIgnoreCase))
if (fileName.StartsWith("WLAN_Cert_Root_", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("WLAN_Cert_Intermediate_", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("WLAN_Cert_Personal_", StringComparison.OrdinalIgnoreCase))
File.Copy(file, Path.Combine(InstallLocation, fileName));
// Copy Wireless Profiles
if (fileName.StartsWith("WLAN_Profile_", StringComparison.InvariantCultureIgnoreCase) &&
fileName.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase))
if (fileName.StartsWith("WLAN_Profile_", StringComparison.OrdinalIgnoreCase) &&
fileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
File.Copy(file, Path.Combine(InstallLocation, fileName));
}
@@ -194,7 +194,7 @@ namespace Disco.ClientBootstrapper.Interop
if (string.IsNullOrWhiteSpace(InstallLocation))
InstallLocation = Path.Combine(Path.GetPathRoot(Environment.SystemDirectory), "Disco");
if (InstallLocation.EndsWith(".wim", StringComparison.InvariantCultureIgnoreCase))
if (InstallLocation.EndsWith(".wim", StringComparison.OrdinalIgnoreCase))
{
// Offline File System (WIM)
Program.Status.UpdateStatus("Installing Bootstrapper (Offline)", "Installing", string.Format("Install Location: {0}", InstallLocation));
@@ -216,7 +216,7 @@ namespace Disco.ClientBootstrapper.Interop
using (var wimImage = wim[i])
wimImageInfo.LoadXml(wimImage.ImageInformation);
var wimImageInfoName = wimImageInfo.SelectSingleNode("//IMAGE/NAME");
if (wimImageInfoName != null && wimImageInfoName.InnerText.Equals(WimImageId, StringComparison.InvariantCultureIgnoreCase))
if (wimImageInfoName != null && wimImageInfoName.InnerText.Equals(WimImageId, StringComparison.OrdinalIgnoreCase))
{
wimImageIndex = i + 1;
Program.Status.UpdateStatus(null, "Analysing WIM", string.Format("Found Image Id '{0}' at Index {1}", WimImageId, wimImageIndex));
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.0725.2102")]
[assembly: AssemblyFileVersion("1.2.0725.2102")]
[assembly: AssemblyVersion("2.0.0626.0000")]
[assembly: AssemblyFileVersion("2.0.0626.0000")]
@@ -1,116 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>
</SchemaVersion>
<ProjectGuid>{CD7BB28C-B74D-4880-8B7E-4487AB5E6AFC}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Disco.Configuration</RootNamespace>
<AssemblyName>Disco.Configuration</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Windows</MyType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>Disco.Configuration.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>Disco.Configuration.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
</ItemGroup>
<ItemGroup>
<Import Include="Microsoft.VisualBasic" />
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="My Project\AssemblyInfo.vb" />
<Compile Include="My Project\Application.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Application.myapp</DependentUpon>
</Compile>
<Compile Include="My Project\Resources.Designer.vb">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="My Project\Settings.Designer.vb">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="My Project\Resources.resx">
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="My Project\Application.myapp">
<Generator>MyApplicationCodeGenerator</Generator>
<LastGenOutput>Application.Designer.vb</LastGenOutput>
</None>
<None Include="My Project\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<CustomToolNamespace>My</CustomToolNamespace>
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Disco.Models\Disco.Models.vbproj">
<Project>{40F222A9-CC05-4035-AFF4-15A78250EF2B}</Project>
<Name>Disco.Models</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-13
View File
@@ -1,13 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.235
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>false</MySubMain>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<ApplicationType>1</ApplicationType>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>
@@ -1,35 +0,0 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("Disco - Configuration")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("Disco")>
<Assembly: AssemblyCopyright("")>
<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("535f903b-6111-4adb-b200-9df78e49d13b")>
' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>
-62
View File
@@ -1,62 +0,0 @@
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.235
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Namespace My.Resources
'This class was auto-generated by the StronglyTypedResourceBuilder
'class via a tool like ResGen or Visual Studio.
'To add or remove a member, edit your .ResX file then rerun ResGen
'with the /str option, or rebuild your VS project.
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Returns the cached ResourceManager instance used by this class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Disco.Configuration.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Overrides the current thread's CurrentUICulture property for all
''' resource lookups using this strongly typed resource class.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set(ByVal value As Global.System.Globalization.CultureInfo)
resourceCulture = value
End Set
End Property
End Module
End Namespace
@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

Some files were not shown because too many files have changed in this diff Show More