| ofs | hex dump | ascii |
|---|
| 0000 | 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 02 55 00 00 01 47 08 06 00 00 00 88 f0 b9 | .PNG........IHDR...U...G........ |
| 0020 | bf 00 00 00 04 73 42 49 54 08 08 08 08 7c 08 64 88 00 00 00 09 70 48 59 73 00 00 5c 46 00 00 5c | .....sBIT....|.d.....pHYs..\F..\ |
| 0040 | 46 01 14 94 43 41 00 00 00 19 74 45 58 74 53 6f 66 74 77 61 72 65 00 77 77 77 2e 69 6e 6b 73 63 | F...CA....tEXtSoftware.www.inksc |
| 0060 | 61 70 65 2e 6f 72 67 9b ee 3c 1a 00 00 20 00 49 44 41 54 78 9c ec dd 79 98 1c 55 b9 3f f0 ef 7b | ape.org..<.....IDATx...y..U.?..{ |
| 0080 | ba 67 c9 ca 92 84 84 99 ee 9e 99 10 44 09 a0 10 82 22 8a 22 70 59 14 81 64 a6 21 41 e0 72 51 b8 | .g..........D...."."pY..d.!A.rQ. |
| 00a0 | 88 8a 5e 05 dc 89 28 0a 8a 8a 0b 22 82 a0 6c c1 9e 99 60 0c 02 22 18 15 64 33 a0 22 83 4a 42 66 | ..^...(...."..l...`.."..d3.".JBf |
| 00c0 | 7a 99 21 2b 90 10 92 59 ba cf fb fb 23 83 bf 80 59 66 a9 ea d3 55 f5 fd 3c 0f 3e 92 4c de f3 0d | z.!+...Y....#...Yf...U..<.>.L... |
| 00e0 | 53 53 f5 76 d5 a9 73 04 44 44 8e 4c cb bc 30 25 86 d2 0c 63 6c a3 a8 36 aa 48 12 8a a9 00 26 41 | SS.v..s.DD.L..0%...cl..6.H....&A |
| 0100 | 31 09 82 49 00 6a 07 bf 7c 37 00 06 80 05 b0 61 f0 d7 7a a1 58 0f c1 7a 00 eb 01 ac 12 d5 bc 8a | 1..I.j..|7.....a..z.X..z........ |
| 0120 | 74 59 63 ba b4 cf ac e8 99 5f b7 ae ec 7f 31 22 8a 24 71 1d 80 88 a2 a1 71 61 67 63 31 1e 3f 42 | tYc......_....1".$q.....qagc1.?B |
| 0140 | a0 07 03 38 68 f0 9f a9 65 18 7a 15 80 bf 03 f8 9b 42 fe 5a 65 06 1e ee 9c 3b 3d 5b 86 71 89 28 | ...8h...e.z......B.Ze....;=[.q.( |
| 0160 | 62 d8 54 11 91 2f 1a 17 76 36 96 aa 62 c7 43 e5 7d 80 1e 01 a0 ce 75 a6 6d 74 03 f8 93 40 7f 17 | b.T../..v6..b.C.}.....u.mt...@.. |
| 0180 | 33 a5 fb d8 64 11 91 17 d8 54 11 91 37 54 a5 a1 2d 7b b8 15 33 57 55 4e 14 e8 9b 5d 47 1a 32 c1 | 3...d....T..7T..-{..3WUN...]G.2. |
| 01a0 | 3f a0 b8 c7 aa 69 ef 6e a9 7f 0c 22 ea 3a 12 11 05 0f 9b 2a 22 1a 95 54 26 3b 4b 8d cc 07 d0 02 | ?....i.n...".:.....*"..T&;K..... |
| 01c0 | 45 d2 75 1e 0f e4 00 b4 1a b1 b7 67 9b 1b ff e2 3a 0c 11 05 07 9b 2a 22 1a b6 19 b7 2d 9f d8 5f | E.u........g....:.....*"....-.._ |
| 01e0 | 5d 7d ba 42 ce 87 e0 10 d7 79 7c f4 ac 40 6f b1 6a 6e 28 a4 93 2f ba 0e 43 44 95 8d 4d 15 11 0d | ]}.B.....y|..@o.jn(../..CD..M... |
| 0200 | 59 a2 2d bf af 40 3f 05 c5 59 00 c6 b9 ce 53 46 af 02 f8 99 aa 5c 53 48 27 57 b8 0e 43 44 95 89 | Y.-..@?..Y....SF.....\SH'W..CD.. |
| 0220 | 4d 15 11 ed 52 7d a6 70 b8 81 bd 04 82 0f 62 eb b2 06 51 65 01 fc 52 45 be 59 68 4e 3e ee 3a 0c | M...R}.p......b...Qe..RE.YhN>.:. |
| 0240 | 11 55 16 36 55 44 b4 43 89 b6 fc 41 a2 f8 22 a0 2d ae b3 54 1c c5 03 30 f8 5c be 39 b5 cc 75 14 | .U.6UD.C...A..".-..T...0.\.9..u. |
| 0260 | 22 aa 0c 6c aa 88 e8 3f d4 df 59 78 93 31 f6 2a 08 4e 06 cf 13 3b a3 00 ee 52 95 4b f9 58 90 88 | "..l...?..Yx.1.*.N...;...R.K.X.. |
| 0280 | 78 b2 24 a2 7f 6b bc ab 73 f7 62 31 fe 59 81 7e 12 40 8d eb 3c 01 32 a0 90 eb aa b5 ff cb 2b d3 | x.$..k..s.b1.Y.~.@..<.2.......+. |
| 02a0 | fb 6c d8 f5 97 13 51 18 b1 a9 22 22 00 40 2a 93 3d 53 45 be 0d 60 8a eb 2c 01 b6 5a 21 9f 2e b4 | .l....Q..."".@*.=SE..`..,..Z!... |
| 02c0 | 24 6f 77 1d 84 88 ca 8f 4d 15 51 c4 35 2e ec 6c 2c c5 62 3f 86 e0 38 d7 59 42 e4 de b8 29 5e c0 | $ow.....M.Q.5..l,.b?..8.YB...)^. |
| 02e0 | 95 da 89 a2 25 ca 6f f1 10 45 9b aa 24 33 b9 0b 4a f1 d8 33 6c a8 3c 77 42 d1 c6 9f 49 b5 66 cf | ....%.o..E..$3..J..3l.<wB...I.f. |
| 0300 | 77 1d 84 88 ca 87 77 aa 88 22 68 5a e6 85 29 55 32 70 23 80 0f ba ce 12 7a 8a df c4 50 fa ef ae | w.....w.."hZ..)U2p#.....z...P... |
| 0320 | 74 d3 2a d7 51 88 c8 5f 6c aa 88 22 26 95 c9 1e ab 22 b7 02 98 ea 3a 4b 84 bc 60 d4 7e 28 9b 6e | t.*.Q.._l.."&...."....:K..`.~(.n |
| 0340 | fc 9d eb 20 44 e4 1f 3e fe 23 8a 0a 55 49 b5 66 2f 55 91 7b c1 86 aa dc f6 b6 62 ee 4f b5 66 17 | ....D..>.#..UI.f/U.{......b.O.f. |
| 0360 | 40 95 1f 66 89 42 8a 3f dc 44 11 30 79 f1 da 09 63 fa b7 fc 1c c0 a9 ae b3 44 9d 42 da fa b4 e6 | @..f.B.?.D.0y...c........D.B.... |
| 0380 | 9c b5 e9 bd 36 b9 ce 42 44 de 62 53 45 14 72 c9 85 b9 3a c4 b0 24 e4 1b 1f 07 cd d3 a5 62 ec 03 | ....6..BD.bSE.r...:..$.......b.. |
| 03a0 | 3d f3 ea f3 ae 83 10 91 77 d8 54 11 85 58 22 93 3f 50 44 ef 06 90 72 9d 85 fe 43 8f 11 fb 81 6c | =.......w.T..X".?PD...r...C....l |
| 03c0 | 73 e3 5f 5c 07 21 22 6f b0 a9 22 0a a9 44 6b fe bd 06 f6 57 0a 99 e0 3a 0b ed d0 06 00 27 e5 5b | s._\.!"o.."..Dk....W...:.....'.[ |
| 03e0 | 52 0f b9 0e 42 44 a3 c7 89 ea 44 21 94 c8 e4 8f 17 e8 3d 6c a8 2a de 6e 00 ee 4b b6 e5 b8 4e 18 | R...BD....D!......=l.*.n..K...N. |
| 0400 | 51 08 b0 a9 22 0a 99 44 26 7f aa 88 2e 06 30 c6 75 16 1a 92 b1 50 2c 4e b6 e6 4e 76 1d 84 88 46 | Q..."..D&.....0.u....P,N..Nv...F |
| 0420 | 87 8f ff 88 42 24 d9 96 3b 0e 8a c5 e0 66 c8 41 34 20 d0 39 b9 96 86 bb 5d 07 21 a2 91 61 53 45 | ....B$..;....f.A4..9....].!..aSE |
| 0440 | 14 12 a9 d6 ec d1 0a b9 1b 40 ad eb 2c 34 62 fd 10 7c 30 df 9c fa 8d eb 20 44 34 7c 6c aa 88 42 | .........@..,4b..|0......D4|l..B |
| 0460 | a0 3e 53 38 dc 88 fd 2d 80 71 ae b3 d0 a8 6d 52 91 63 0a cd c9 c7 5d 07 21 a2 e1 61 53 45 14 70 | .>S8...-.q....mR.c....].!..aSE.p |
| 0480 | a9 f6 ec 74 6b f1 a8 40 f6 72 9d 85 3c b3 4e 55 0e 2f a4 93 2b 5c 07 21 a2 a1 e3 44 75 a2 00 ab | ...tk..@.r..<.NU./..+\.!...Du... |
| 04a0 | 5f 54 98 04 8b 7b d8 50 85 ce 64 11 bd b7 ee 8e 9e c9 ae 83 10 d1 d0 b1 a9 22 0a a8 59 d7 2f ab | _T...{.P..d.............."..Y./. |
| 04c0 | 32 25 7b 97 42 f6 73 9d 85 7c 31 23 1e 1f c8 60 a9 c6 5d 07 21 a2 a1 61 53 45 14 50 6b 26 ed f5 | 2%{.B.s..|1#...`..].!..aSE.Pk&.. |
| 04e0 | 1d 00 ef 76 9d 83 fc a3 22 47 25 d7 e7 af 72 9d 83 88 86 86 73 aa 88 02 28 d1 9a 3f 43 a0 b7 b9 | ...v...."G%...r.....s...(..?C... |
| 0500 | ce 41 65 a2 38 3d 9f 4e fd c2 75 0c 22 da 39 36 55 44 01 93 6a cb ce 54 95 27 00 8c 75 9d 85 ca | .Ae.8=.N..u.".96UD..j..T.'..u... |
| 0520 | 66 93 2d 99 59 dd a7 27 9e 73 1d 84 88 76 8c 8f ff 88 02 64 c6 3d cb 6b d4 ca ed 60 43 15 35 e3 | f.-.Y..'.s...v.....d.=.k...`C.5. |
| 0540 | 8d b1 0b 67 66 3a aa 5d 07 21 a2 1d 63 53 45 14 20 7d 9b 6b be 0e c1 5b 5d e7 20 07 04 87 6c 30 | ...gf:.].!..cSE..}.k...[].....l0 |
| 0560 | 13 bf e2 3a 06 11 ed 18 1f ff 11 05 44 a2 35 ff 5e 81 3e 08 7e 18 8a 32 0b e0 bd f9 96 d4 43 ae | ...:........D.5.^.>.~..2......C. |
| 0580 | 83 10 d1 7f 62 53 15 20 75 4b 7a c6 c6 b7 0c 34 0a b4 49 45 12 0a 99 02 60 12 80 3d 00 d9 fa 38 | ....bS..uKz....4..IE....`..=...8 |
| 05a0 | 48 b5 0a 22 03 00 20 b0 7d 00 5e b2 30 eb a1 58 2f 46 0b d6 9a ae aa aa 81 ae ae 53 9b 5e 76 f7 | H.."....}.^.0..X/F.........S.^v. |
| 05c0 | 37 a1 e1 4a 64 f2 63 44 f4 69 00 33 5c 67 21 c7 04 cf c5 5e 29 bd b5 eb 9c a6 5e d7 51 68 68 66 | 7..Jd.cD.i.3\g!....^).....^.Qhhf |
| 05e0 | dc b3 bc 66 cb c6 31 0d 26 66 1b 21 48 88 ea 54 15 99 0c c5 1e 80 8c 07 f0 ba 73 37 44 07 a0 78 | ...f..1.&f.!H..T..........s7D..x |
| 0600 | 49 44 d7 03 58 0f c5 0b 2a d2 59 ea 8f 77 f5 cc af 5b e7 f0 af 42 bb c0 a6 aa 42 4d cb bc 30 a5 | ID..X...*.Y..w...[...B....BM..0. |
| 0620 | 4a 06 de 09 e0 30 28 0e 54 91 83 04 da e0 55 7d 85 ae 11 95 a7 61 f0 b4 aa 3c 55 65 06 1e ee 9c | J....0(.T.....U}.....a...<Ue.... |
| 0640 | 3b 3d eb 55 7d f2 56 aa 35 7b 95 42 2e 71 9d 83 2a c6 d7 f2 2d a9 2f b9 0e 41 ff 69 7a e6 f9 dd | ;=.U}.V.5{.B.q..*...-./..A.iz... |
| 0660 | fa 51 7d 38 80 c3 0c ec 41 2a f2 56 00 d3 e1 dd 1d e6 97 a0 f8 3b 0c 9e 86 e2 a9 98 94 1e ed 6a | .Q}8....A*.V.........;.........j |
| 0680 | 6e fa a7 47 b5 69 94 d8 54 55 88 a9 b7 ac 1a 57 5d db 7f 34 0c 8e 07 70 34 14 6f 72 10 a3 5b a0 | n..G.i..TU.....W]..4...p4.or..[. |
| 06a0 | bf b7 30 f7 16 35 7e ff aa f4 de 6b 1d 64 a0 37 a8 5f 54 78 ab 29 d9 65 00 b8 08 24 bd 66 00 31 | ..0..5~....k.d.7._Tx.).e...$.f.1 |
| 06c0 | 1c 92 9f 93 7a c6 75 90 a8 9b 71 cf f2 9a fe 2d d5 ef 56 95 13 a0 38 16 c0 4c 94 ff 11 fd 3a 00 | ....z.u...q....-..V...8..L....:. |
| 06e0 | 7f 54 91 fb ec 80 b9 af 67 5e 7d be cc e3 d3 20 36 55 0e cd b8 6d f9 c4 fe ea ea 93 ad 98 b4 40 | .T......g^}.....6U...m.........@ |
| 0700 | 8f 05 50 e3 3a d3 36 2c 80 87 20 b8 a5 a6 b7 af 6d c5 87 f6 dd e8 3a 50 54 25 5b 73 bf 07 f0 1e | ..P.:.6,........m.....:PT%[s.... |
| 0720 | d7 39 a8 b2 28 e4 77 85 96 e4 d1 ae 73 44 51 22 93 1f 03 e0 78 11 4d 03 f8 00 80 f1 8e 23 bd d1 | .9..(.w.....sDQ"....x.M......#.. |
| 0740 | 32 11 bd b5 cf 0c dc b9 7a ce 8c 35 ae c3 44 09 9b aa 72 53 95 44 6b e1 48 23 f6 23 0a 99 0b a0 | 2.......z..5..D...rS.Dk.H#.#.... |
| 0760 | d6 75 a4 21 d8 02 e0 97 0a b9 b5 a0 89 fb 91 96 92 eb 40 51 91 ca 64 9b 55 a4 d5 75 0e aa 58 a7 | .u.!..............@Q..d.U..u..X. |
| 0780 | e4 5b 52 8b 5d 87 88 8a 86 f6 ae 43 ac 35 1f 01 30 1f c0 44 d7 79 86 60 00 8a fb 44 f4 56 b3 c9 | .[R.]......C.5..0..D.y.`...D.V.. |
| 07a0 | 2e e1 3c 3c ff b1 a9 2a 93 59 d7 2f ab 5a 3b 69 ca 7c 55 b9 04 c0 fe ae f3 8c c2 0b 0a b9 a6 b7 | ..<<...*.Y./.Z;i.|U............. |
| 07c0 | ba f6 ba 75 27 4f 79 c5 75 98 30 6b bc b9 b3 b6 34 3e f6 2c 80 26 d7 59 a8 62 ad 98 a8 af cc ec | ...u'Oy.u.0k....4>.,.&.Y.b...... |
| 07e0 | 48 cf ec 77 1d 24 b4 54 25 d9 96 ff 20 80 cf 01 78 bb eb 38 a3 f0 32 80 eb 06 b4 ea bb 9c da e1 | H..w.$.T%.......x..8..2......... |
| 0800 | 1f 36 55 3e 9b 99 e9 a8 7e 45 c6 9f ae 90 2f 02 d8 d7 75 1e 0f 6d 54 c8 75 50 7c b3 90 4e be e8 | .6U>....~E..../...u..mT.uP|..N.. |
| 0820 | 3a 4c 18 a5 32 d9 8b 54 e4 1a d7 39 a8 c2 29 3e 9a 4f a7 ae 73 1d 23 74 16 a8 49 1d 90 7b bf aa | :L..2..T...9..)>.O..s.#t..I..{.. |
| 0840 | 5c 06 60 96 eb 38 1e ea 53 91 9f ab c8 57 bb e7 26 0a ae c3 84 0d 9b 2a 9f 24 32 f9 31 02 bd 00 | \.`..8..S....W..&......*.$2.1... |
| 0860 | 82 4f 03 a8 73 9d c7 2f 02 7d 05 c0 75 c5 81 aa 6f f1 55 5f ef 0c 2e a1 b0 02 21 3e 76 c8 33 2f | .O..s../.}..u...o.U_......!>v.3/ |
| 0880 | a8 ca 3e 85 74 72 8b eb 20 a1 90 d1 58 d2 e4 cf 86 e2 b3 08 d7 07 e1 37 ea 53 91 9f 57 c9 c0 d7 | ..>.tr......X..........7.S..W... |
| 08a0 | f9 e6 b7 77 b8 88 a0 0f 52 ad d9 a3 21 78 0a 82 6f 23 e4 17 45 85 4c 50 c8 25 b1 aa e2 73 a9 4c | ...w....R...!x..o#..E.LP.%...s.L |
| 08c0 | f6 22 64 34 e6 3a 53 28 08 3e 8e 90 1f 3b e4 99 bd 8d d8 f3 5d 87 08 83 54 26 3b 2b 29 f9 47 a0 | ."d4.:S(.>...;......]...T&;+).G. |
| 08e0 | f8 29 c2 dd 50 01 40 8d a8 9e 57 b4 f1 7f a4 5a b3 0b 66 dc b3 bc 92 5e 94 0a 2c de a9 f2 50 22 | .)..P.@...W....Z..f....^..,...P" |
| 0900 | 93 af 87 c1 37 44 f5 4c d7 59 9c 51 3c a5 46 3e 5a 68 4e 3e ee 3a 4a 50 35 de dc 59 5b 1c 6f b2 | ....7D.L.Y.Q<.F>ZhN>.:JP5..Y[.o. |
| 0920 | 02 d9 cb 75 16 0a 8c 17 6a c6 f5 35 ad 38 71 df 3e d7 41 82 28 75 7b 76 0f 5b 6d 16 08 f4 42 00 | ...u....j..5.8q.>.A.(u{v.[m...B. |
| 0940 | 51 fd 60 b8 42 55 3e 5e 48 27 ef 73 1d 24 c8 78 a7 ca 03 b3 ae 5f 56 95 6a cd 5e 2a a2 ff 8a 74 | Q.`.BU>^H'.s.$.x....._V.j.^*...t |
| 0960 | 43 05 00 82 43 44 f5 4f c9 d6 dc b5 8d 77 75 ee ee 3a 4e 10 d9 71 e6 2c 36 54 34 4c 7b f7 6d ae | C...CD.O.....wu..:N..q.,6T4L{.m. |
| 0980 | 39 c3 75 88 c0 51 95 44 26 7f ae 56 cb 73 02 fd 04 a2 db 50 01 c0 0c 11 bd 37 d9 96 bb 33 b9 30 | 9.u..Q.D&..V.s.....P.....7...3.0 |
| 09a0 | c7 bb e4 23 c4 3b 55 a3 54 b7 b0 3b 19 8b 95 16 42 70 84 eb 2c 15 28 67 60 e7 65 5b 1a 1f 71 1d | ...#.;U.T..;....Bp..,.(g`.e[..q. |
| 09c0 | 24 30 54 25 d9 9e ef 80 e2 2d ae a3 50 b0 28 e4 9f 85 8e c4 4c 2c 10 eb 3a 4b 10 4c cf 3c bf 5b | $0T%.....-..P.(.....L,..:K.L.<.[ |
| 09e0 | bf 54 df 28 d0 66 d7 59 2a d0 7a a3 f6 ec 6c ba f1 d7 ae 83 04 0d 9b aa 51 48 b5 65 4f 52 95 9f | .T.(.f.Y*.z...l.........QH.eOR.. |
| 0a00 | 01 d8 d3 75 96 0a 56 14 e8 15 b9 8e d4 e5 3c d9 ef 5a 43 a6 eb fd 56 cc dd ae 73 50 30 a9 ca 09 | ...u..V.......<..ZC...V...sP0... |
| 0a20 | 7c 7c b3 6b c9 f6 dc 6c 58 fc 02 5c ae 64 67 54 21 3f d8 4d 37 5e cc 25 3b 86 8e 8f ff 46 62 a9 | ||.k...lX..\.dgT!?.M7^.%;....Fb. |
| 0a40 | c6 53 ad d9 05 aa f2 4b b0 a1 da 95 b8 42 2e 4b ee 9f ff 65 22 93 e7 7f ab 5d b0 30 9c 70 4c 23 | .S.....K.....B.K...e"....].0.pL# |
| 0a60 | 26 50 1e 3f 3b a3 2a a9 4c f6 22 58 3c 0c 36 54 bb 22 02 fd c4 46 4c 78 b8 21 d3 c5 ff 56 43 c4 | &P.?;.*.L."X<.6T."...FLx.!...VC. |
| 0a80 | 3b 55 c3 d4 98 e9 9c 56 92 d8 62 00 87 b9 ce 12 40 39 1b 33 1f ec 9e 93 f8 9b eb 20 95 28 91 c9 | ;U.....V..b.....@9.3.........(.. |
| 0aa0 | d7 8b 68 16 d1 9e d7 41 a3 53 44 11 0d f9 79 a9 1e d7 41 2a cd 94 cc 9a f1 35 d2 b7 50 a0 1f 70 | ..h....A.SD...y...A*.....5..P..p |
| 0ac0 | 9d 25 80 5e 14 a3 a7 e5 e6 36 3c e0 3a 48 a5 e3 9d aa 61 68 c8 74 35 95 24 f6 47 b0 a1 1a a9 94 | .%.^.....6<.:H....ah.t5.$.G..... |
| 0ae0 | 29 d9 87 53 99 ec b1 ae 83 54 a8 73 c1 86 8a 46 27 2e 71 3d db 75 88 4a 93 c8 e4 f7 1c 23 5b ee | )..S.....T.s...F'.q=.u.J.....#[. |
| 0b00 | 67 43 35 62 7b aa 95 5f 27 5b 73 a7 bb 0e 52 e9 d8 54 0d 51 72 51 ee 00 2b e6 21 84 7f ed 12 bf | gC5b{.._'[s...R..T.QrQ..+.!..... |
| 0b20 | 8d 57 91 25 a9 d6 6c 8b eb 20 95 46 8c 9e e5 3a 03 85 02 9b aa 6d 34 b5 af 6c 30 62 1f 51 c8 e1 | .W.%..l....F...:.....m4..l0b.Q.. |
| 0b40 | ae b3 04 5c 35 80 3b 92 ad b9 4f bb 0e 52 c9 d8 54 0d 41 22 93 7f 0f 4a 78 18 40 bd eb 2c 21 51 | ...\5.;...O..R..T.A"...Jx.@..,!Q |
| 0b60 | a3 90 85 a9 d6 2c e7 7f 0c 4a b6 e5 0e 85 62 1f d7 39 28 f8 14 b2 5f fd a2 c2 5b 5d e7 a8 04 a9 | .....,...J....b..9(..._...[].... |
| 0b80 | 4c 76 ff a2 c6 1f 52 c8 7e ae b3 84 84 00 b8 3a d1 9a bf 12 aa 9c 3e b4 1d 6c aa 76 21 d1 96 3f | Lv....R.~......:......>..l.v!..? |
| 0ba0 | 51 44 ef 03 b0 9b eb 2c 21 13 53 c8 8f 13 99 fc c5 ae 83 54 04 c5 69 ae 23 50 78 98 92 8d fc f1 | QD.....,!.S........T..i.#Px..... |
| 0bc0 | 94 ca 64 67 a9 c8 c3 50 24 5d 67 09 1b 81 5e 9a 6c cb ff d0 75 8e 4a c4 a6 6a 27 12 6d f9 b7 8b | ..dg...P$]g...^.l...u.J..j'.m... |
| 0be0 | 6a 06 40 ad eb 2c 61 25 a2 57 25 32 f9 73 5d e7 70 4e c0 b5 72 c8 3b 82 b4 eb 08 2e 25 ef cc ed | j.@..,a%.W%2.s].pN..r.;.....%... |
| 0c00 | a3 22 bf 06 b0 87 eb 2c 21 f6 d1 64 6b ee 72 d7 21 2a 0d 6f df ed 40 aa 2d 3b 53 55 fe 08 2e 99 | .".....,!..dk.r.!*.o..@.-;SU.... |
| 0c20 | 50 0e 25 85 a4 0b 2d c9 45 ae 83 b8 90 c8 e4 0f 14 d1 a7 5d e7 a0 70 89 49 e9 2d 5d cd 4d ff 74 | P.%...-.E..........]..p.I.-].M.t |
| 0c40 | 9d a3 dc 92 0b 73 75 88 73 c9 84 72 11 e8 a7 72 2d 0d d7 b8 ce 51 29 78 a7 6a 3b ea db 0b 09 55 | .....su.s..r...r-....Q)x.j;....U |
| 0c60 | b9 07 6c a8 ca 25 26 d0 db 92 ad b9 77 bb 0e e2 84 e0 04 d7 11 28 7c 4a 88 45 ee b8 9a 9e 79 7e | ..l..%&.....w........(|J.E....y~ |
| 0c80 | 37 89 eb af c1 86 aa 6c 14 f2 ed 54 5b 36 d2 77 46 b7 c5 a6 ea 0d ea ee e8 99 2c 56 7f 0b 20 e5 | 7......l...T[6.wF.........,V.... |
| 0ca0 | 3a 4b c4 8c 01 b0 38 b9 28 77 80 eb 20 e5 26 d0 c8 5d fc a8 0c 34 5a cd 7a e3 cd 9d b5 03 52 b5 | :K....8.(w....&..]...4Z.z.....R. |
| 0cc0 | 44 21 6f 73 9d 25 62 8c aa dc d2 90 e9 7a 9f eb 20 95 80 4d d5 b6 54 25 16 2f de 24 d0 37 bb 8e | D!os.%b......z.....M..T%./.$.7.. |
| 0ce0 | 12 51 7b a0 84 bb 66 dc b6 7c a2 eb 20 e5 32 f5 96 55 e3 00 bc d3 75 0e 0a a5 23 13 99 fc 18 d7 | .Q{...f..|....2..U....u...#..... |
| 0d00 | 21 ca a5 34 3e 76 0d 80 68 de ed 76 af c6 8a 69 6b 6a 5f d9 e0 3a 88 6b 6c aa b6 91 6a cb 7d 16 | !..4>v..h..v...ikj_..:.kl...j.}. |
| 0d20 | 82 93 5c e7 88 b8 19 7d 35 35 37 b8 0e 51 2e b5 b5 bd 6f c7 d6 f5 5f 88 bc 56 23 31 9d ed 3a 44 | ..\....}557..Q....o..._..V#1..:D |
| 0d40 | 39 0c 3e 7e e2 12 2d 6e ed 51 b4 f1 5f cc ba 7e 59 95 eb 20 2e b1 a9 1a 54 df 5e 78 87 42 be e2 | 9.>~..-n.Q.._..~Y.......T.^x.B.. |
| 0d60 | 3a 07 01 00 d2 51 59 c3 ca 8a 39 c2 75 06 0a 2f b1 1a fa e3 2b 91 c9 cf 50 95 c8 7c 10 ab 70 6f | :....QY...9.u../....+...P..|..po |
| 0d80 | 5f bd e7 d4 af ba 0e e1 12 9b 2a 6c dd c2 40 ac de 09 20 d2 1d 76 25 51 c8 35 0d 6d 5d 07 bb ce | _.........*l..@......v%Q.5.m]... |
| 0da0 | e1 3b 45 e8 2f 7a e4 8e 45 b8 9b f6 19 f7 2c af 11 e8 2f 00 44 66 ca 40 a5 13 e8 25 c9 4c ee 83 | .;E./z..E.....,.../.Df.@...%.L.. |
| 0dc0 | ae 73 b8 c2 a6 0a 00 04 3f 17 68 e4 9f 05 57 98 5a 0b 73 67 dd 92 9e b1 ae 83 f8 4a 10 89 c7 33 | .s......?.h...W.Z.sg.......J...3 |
| 0de0 | e4 86 40 df ee 3a 83 9f fa 36 d7 5c 0d c1 21 ae 73 d0 eb 08 04 3f 6d 68 ef da db 75 10 17 22 df | ..@..:...6.\..!.s....?mh...u..". |
| 0e00 | 54 25 33 b9 d3 b8 c9 66 85 52 bc 29 d6 5b fc 82 eb 18 7e a9 5b d8 9d 04 97 ed 20 7f 4d 0e eb c5 | T%3....f.R.).[....~.[.......M... |
| 0e20 | 2d d9 9e 9b 0d c5 47 5d e7 a0 ed 9a 6c ad f9 b6 eb 10 2e 44 ba a9 9a bc 78 ed 04 08 22 f9 8d 0f | -.....G]....l......D....x..."... |
| 0e40 | 90 cf 34 dc d9 f5 16 d7 21 fc 50 15 1b 38 c8 75 06 0a 3f ab 26 7c c7 d9 02 35 b0 f8 21 22 7e 0d | ..4.....!.P..8.u..?.&|...5..!"~. |
| 0e60 | ab 70 f3 52 ad d9 a3 5d 87 28 b7 48 1f 90 63 fa b7 7c 05 dc 24 b9 d2 55 db 98 b9 2e 8c 9b 77 aa | .p.R...].(.H..c..|..$..U......w. |
| 0e80 | 48 f8 2e 76 54 79 14 07 ba 8e e0 b5 c4 cc c2 85 00 0e 73 9d 83 76 4e 21 d7 cd b8 67 79 8d eb 1c | H..vTy............s..vN!...gy... |
| 0ea0 | e5 14 d9 a6 6a 70 91 c9 8f b9 ce 41 43 f2 9e 64 5b 3e 74 1b c4 aa c8 9b 5c 67 a0 f0 13 e8 7e ae | ....jp.....AC..d[>t.....\g....~. |
| 0ec0 | 33 78 a9 e9 8e 95 53 05 ca 3d e7 82 61 df fe 57 ab ff cf 75 88 72 8a 66 53 a5 2a 28 e1 3a f0 6d | 3x....S..=..a..W...u.r.fS.*(.:.m |
| 0ee0 | bf 20 f9 ce e4 c5 6b 27 b8 0e e1 29 e5 56 1a e4 3f 0b 13 aa e3 ac 54 15 bb 1a c0 ee ae 73 d0 d0 | ......k'...).V..?.....T......s.. |
| 0f00 | 28 e4 8b 75 99 9e c8 ec 50 12 c9 a6 2a d9 9a 3f 09 c0 bb 5c e7 a0 61 d9 7b 4c ff 96 8b 5c 87 f0 | (..u....P...*..?...\..a.{L...\.. |
| 0f20 | 92 42 1a 1d 47 a0 08 10 d1 46 d7 19 bc 92 5c 94 3b 40 21 f3 5d e7 a0 61 19 1b 93 e2 65 ae 43 94 | .B..G....F....\.;@!.]..a....e.C. |
| 0f40 | 4b f4 9a 2a 55 11 51 2e f2 19 4c 9f 49 64 f2 e1 78 5b 6e a9 c6 05 ca f9 7c e4 3f 45 0a 19 8d b9 | K..*U.Q...L.Id..x[n.....|.?E.... |
| 0f60 | 8e e1 89 12 be 86 28 5e b7 82 ef ec ba 4c 77 a8 1e 43 ef 48 e4 0e ce 44 6b e1 14 6e b8 19 58 bb | ......(^.....Lw..C.H...Dk..n..X. |
| 0f80 | 19 b1 9f 70 1d c2 0b c9 55 f9 bd 00 c4 5d e7 a0 48 a8 6a 2a 76 4e 76 1d 62 b4 06 17 03 8e ec a2 | ...p....U....]..H.j*vNv.b....... |
| 0fa0 | 92 01 17 8b 49 e9 f3 ae 43 94 43 e4 9a 2a 23 f6 62 d7 19 68 e4 14 f2 f1 c1 4d 88 03 4d ab 24 f0 | ....I...C.C..*#.b..h.....M..M.$. |
| 0fc0 | 17 39 0a 8e 52 75 2c f0 c7 9b 85 f9 0c 80 d0 bd 05 1c 21 f3 a2 30 b7 2a 52 4d 55 b2 3d 37 5b 21 | .9..Ru,...........!..0.*RMU.=7[! |
| 0fe0 | 87 bb ce 41 a3 b2 67 f5 98 fe b3 5d 87 18 2d 15 99 e4 3a 03 45 47 d0 8f b7 44 26 5f 0f 45 8b eb | ...A..g....]..-...:.EG...D&_.E.. |
| 1000 | 1c 34 2a 55 71 33 10 fa 37 ee 23 d5 54 89 d5 50 3c 3a a2 e0 af a2 1c 2b 95 02 7d 91 a3 60 51 1b | .4*Uq3..7.#.T..P<:.....+..}..`Q. |
| 1020 | ec 3b a3 22 7a 3e f8 b6 76 e0 a9 ca 87 c3 be 6e 55 64 9a aa a9 b7 ac 1a a7 90 53 5c e7 20 4f cc | .;."z>..v......nUd........S\..O. |
| 1040 | 6c 68 ef 0a f4 7e 5f 0a 19 ef 3a 03 45 87 51 1b dc 47 e6 5b 17 fe 3d c3 75 0c f2 c4 1e bd 9b 6b | lh...~_...:.E.Q..G.[..=.u......k |
| 1060 | 43 bd 2d 5c 64 9a aa ea da fe 16 00 bc 90 85 84 b5 e6 4c d7 19 46 43 a0 d5 ae 33 50 74 58 31 81 | C.-\d.............L..FC...3PtX1. |
| 1080 | bd 3b 90 68 2d 1c 09 60 ba eb 1c e4 0d 51 0d f4 b9 7b 57 22 d3 54 a9 48 a8 bf 91 51 a3 d0 f9 b3 | .;.h-..`.....Q...{W".T.H...Q.... |
| 10a0 | ae 5f 16 d8 c7 01 41 be c8 51 f0 88 68 60 8f 37 31 e1 be 08 47 d0 89 75 77 f4 04 fa 71 f4 ce 44 | ._....A..Q..h`.71...G..uw...q..D |
| 10c0 | a2 a9 4a 64 f2 f5 02 7d 8f eb 1c e4 1d 81 ec b5 6e 8f c9 ff e5 3a c7 48 89 6a 60 1b 42 0a 20 8b | ..Jd...}........n....:.H.j`.B... |
| 10e0 | 40 36 55 8d 37 77 d6 42 31 d7 75 0e f2 54 95 89 97 4e 77 1d c2 2f 91 68 aa 0c ec 99 00 c2 b1 f8 | @6U.7w.B1.u..T...Nw../.h........ |
| 1100 | 1d fd 9b 35 c1 7e 04 48 54 2e 22 6a 5d 67 18 89 d2 b8 d8 c9 e0 96 34 a1 23 12 de bb 8f 91 68 aa | ...5.~.HT."j]g........4.#.....h. |
| 1120 | 54 38 41 3d 8c 44 f5 c4 99 99 8e 40 ce 4d 52 48 bf eb 0c 14 1d aa d2 e7 3a c3 88 08 78 ee 0e a7 | T8A=.D.....@.MRH........:...x... |
| 1140 | d9 c9 85 b9 3a d7 21 fc 10 fa a6 6a f0 d9 ed a1 ae 73 90 f7 14 32 61 83 4c 7c a7 eb 1c 23 62 10 | ....:.!....j.....s...2a.L|...#b. |
| 1160 | cc 8b 1c 05 52 20 9b f8 ad 5b eb 1c eb 3a 06 f9 42 10 c7 71 ae 43 f8 21 f4 4d 55 ac ba 78 2c f8 | ....R....[...:..B..q.C.!.MU..x,. |
| 1180 | e8 2f cc 8e 77 1d 60 24 8c 5a 36 55 54 36 06 36 70 4d 55 7d ac 7b 36 00 ae e7 16 5e 81 3c 77 ef | ./..w.`$.Z6UT6.6pMU}.{6....^.<w. |
| 11a0 | 4a e8 9b 2a 85 bc d7 75 06 f2 8f 68 30 5f 40 b0 6a 5e 71 9d 81 a2 43 21 1b 5c 67 18 ae 58 a9 f4 | J..*...u...h0_@.j^q...C!.\g..X.. |
| 11c0 | 5e d7 19 c8 57 81 3c 77 ef 4a e8 9b 2a b1 1a cc c7 43 34 34 82 59 75 4b 7a c6 ba 8e 31 5c 22 ba | ^...W.<w.J..*....C44.YuKz...1\". |
| 11e0 | ce 75 06 8a 0e 23 36 70 c7 9b 42 78 ee 0e b7 a9 89 4c 7e 86 eb 10 5e 0b 75 53 35 3d f3 fc 6e 10 | .u...#6p..Bx.....L~...^.uS5=..n. |
| 1200 | ec ef 3a 07 f9 aa 2a d6 5f 0c dc 9c 39 51 5d ef 3a 03 45 c7 80 56 05 ef 78 13 70 9f d6 90 33 c6 | ..:...*._...9Q].:.E..V..x.p...3. |
| 1220 | 1e e1 3a 83 d7 42 dd 54 f5 4b f5 c1 08 f9 df 91 00 b1 1a b8 2d 6b fa e2 03 81 bb 73 40 01 56 94 | ..:..B.T.K..........-k.....s@.V. |
| 1240 | 40 35 55 4d ed 2b 1b 00 84 76 81 48 da ca aa 09 dc b9 7b 57 42 dd 70 18 b1 07 b9 ce 40 fe 53 c8 | @5UM.+...v.H......{WB.p.....@.S. |
| 1260 | 81 ae 33 0c d7 ea a7 f7 59 07 f0 0d 40 2a 8b de 9e 79 7b 07 aa a9 2a 69 8c e7 ee 08 30 6a 03 77 | ..3.....Y...@*...y{...*i....0j.w |
| 1280 | ee de 95 50 37 55 50 1c e0 3a 02 95 45 f0 4e c0 0b c4 02 c8 b9 8e 41 e1 a7 90 2e 88 a8 eb 1c c3 | ...P7UP..:..E.N.......A......... |
| 12a0 | c2 73 77 24 a8 04 ef 03 f1 ae 84 bd a9 0a dd 24 38 da ae 7d 5d 07 18 a1 2e d7 01 28 fc 04 da e9 | .sw$...........$8..}]......(.... |
| 12c0 | 3a c3 70 29 84 e7 ee 68 98 dc 78 57 67 a8 56 cc 0f 75 53 a5 46 9a 5c 67 a0 b2 d8 2d 88 3f 98 2a | :.p)...h..xWg.V..uS.F.\g...-.?.* |
| 12e0 | 12 b8 8b 1d 05 52 e0 8e 33 51 e5 b9 3b 22 b4 14 ae eb 74 78 9b aa a5 1a 87 22 e1 3a 06 95 47 10 | .....R..3Q..;"....tx.....".:..G. |
| 1300 | 7f 30 8d da 7f b8 ce 40 11 20 78 d6 75 84 e1 52 91 06 d7 19 a8 3c 4a 1a 0b dc b9 7b 67 42 db 54 | .0.....@..x.u..R.....<J....{gB.T |
| 1320 | 35 bc 98 9d 02 20 ee 3a 07 95 47 09 b1 bd 5d 67 18 2e 51 7d da 75 06 8a 00 c1 df 5d 47 18 81 c0 | 5......:..G...]g..Q}.u.....]G... |
| 1340 | fd 3c d3 c8 88 68 a8 be d7 a1 6d aa 4a a5 18 5f c7 8d 10 a3 36 70 df ef 81 62 35 9b 2a f2 9d 96 | pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Authentication;
using System.Threading.Tasks;
using System.Web.Http;
using Tango.BL;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Core.DB;
using Tango.Logging;
using Tango.MachineService.Models;
using Tango.PPC.Common.Web;
using Tango.Web.Controllers;
using Tango.Web.Helpers;
using Tango.Web.SMO;
using Tango.Web.Storage;
using System.Data.Entity;
using Tango.Web.Security;
using Tango.Web.ActiveDirectory;
using Tango.Core.Cryptography;
using Tango.MachineService.Filters;
using Tango.BL.DTO;
namespace Tango.MachineService.Controllers
{
public class PPCController : TangoController<PPCController.TokenObject>
{
private static List<PPCPendingUpload> _pendingUploads;
private static List<PPCPendingUpdate> _pendingUpdates;
private ActiveDirectoryManager _ad_manager;
public const int SQL_TEMP_CREDENTIALS_EXP_MINUTS = 20;
public class TokenObject
{
public LoginMode Mode { get; set; }
public String UserGuid { get; set; }
public String MachineGuid { get; set; }
}
#region Constructors
static PPCController()
{
_pendingUploads = new List<PPCPendingUpload>();
_pendingUpdates = new List<PPCPendingUpdate>();
}
public PPCController()
{
_ad_manager = new ActiveDirectoryManager();
}
#endregion
#region Setup & Update
[HttpPost]
[JwtTokenFilter]
public MachineSetupResponse MachineSetup(MachineSetupRequest request)
{
MachineSetupResponse response = new MachineSetupResponse();
response.NotifyCompletedToken = Guid.NewGuid().ToString();
LogManager.Log("Setup request received: " + request.ToString());
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.Include(x => x.Organization).SingleOrDefault(x => x.Guid == machine_guid);
if (machine == null)
{
throw new AuthenticationException("The specified serial number could not be found.");
}
if (machine.SetupActivation && String.IsNullOrWhiteSpace(machine.OsKey))
{
throw new InvalidDataException("The specified machine is configured to perform an OS activation but is not associated with an OS activation key.");
}
if (String.IsNullOrWhiteSpace(request.DeviceID))
{
throw new InvalidDataException("Device id not set.");
}
if (String.IsNullOrWhiteSpace(request.DeviceName))
{
throw new InvalidDataException("Device name not set.");
}
if (machine.IsDeviceRegistered && machine.DeviceId != request.DeviceID)
{
throw new InvalidDataException("The specified machine is already registered and device id is invalid.");
}
machine.DeviceName = request.DeviceName;
machine.DeviceId = request.DeviceID;
machine.IsDeviceRegistered = true;
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
response.Version = latest_machine_version.Version;
response.FirmwareVersion = latest_machine_version.FirmwareVersion;
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
var blob = container.GetBlockBlobReference(latest_machine_version.BlobName);
response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
{
response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
}
DbCredentials credentials = new DbCredentials();
using (SmoManager smo = new SmoManager())
{
credentials = smo.CreateRandomLoginAndUser();
Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
m.DeleteLoginAndUser(credentials.UserName);
}
});
}
response.DataSource = new DataSource()
{
Address = MachineServiceConfig.DB_ADDRESS,
Catalog = MachineServiceConfig.DB_CATALOG,
UserName = credentials.UserName,
Password = credentials.Password,
IntegratedSecurity = false,
Type = DataSourceType.SQLServer,
};
response.OSKey = machine.OsKey;
response.SetupActivation = machine.SetupActivation;
response.SetupRemoteAssistance = machine.SetupRemoteAssistance;
response.SetupUWF = machine.SetupUwf;
response.SetupFirmware = machine.SetupFirmware;
response.IsDemo = machine.IsDemo;
response.Organization = machine.Organization.Name;
TangoUpdate tangoUpdate = new TangoUpdate();
tangoUpdate.ApplicationVersion = latest_machine_version.Version;
tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion;
tangoUpdate.MachineGuid = machine.Guid;
tangoUpdate.StartDate = DateTime.UtcNow;
tangoUpdate.UpdateStatus = TangoUpdateStatuses.SetupStarted;
db.TangoUpdates.Add(tangoUpdate);
machine.ProductionDate = DateTime.UtcNow;
db.SaveChanges();
_pendingUpdates.Add(new PPCPendingUpdate()
{
Token = response.NotifyCompletedToken,
TangoUpdateGuid = tangoUpdate.Guid,
});
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
{
DownloadUpdateResponse response = new DownloadUpdateResponse();
response.NotifyCompletedToken = Guid.NewGuid().ToString();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
db.Configuration.LazyLoadingEnabled = false;
String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
if (machine == null)
{
throw new AuthenticationException("The specified serial number could not be found.");
}
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
response.Version = latest_machine_version.Version;
response.FirmwareVersion = latest_machine_version.FirmwareVersion;
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
var blob = container.GetBlockBlobReference(latest_machine_version.BlobName);
response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
{
response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
}
DbCredentials credentials = new DbCredentials();
using (SmoManager smo = new SmoManager())
{
credentials = smo.CreateRandomLoginAndUser();
Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
m.DeleteLoginAndUser(credentials.UserName);
}
});
}
response.DataSource = new DataSource()
{
Address = MachineServiceConfig.DB_ADDRESS,
Catalog = MachineServiceConfig.DB_CATALOG,
UserName = credentials.UserName,
Password = credentials.Password,
IntegratedSecurity = false,
Type = DataSourceType.SQLServer,
};
TangoUpdate tangoUpdate = new TangoUpdate();
tangoUpdate.ApplicationVersion = latest_machine_version.Version;
tangoUpdate.FirmwareVersion = latest_machine_version.FirmwareVersion;
tangoUpdate.MachineGuid = machine.Guid;
tangoUpdate.StartDate = DateTime.UtcNow;
tangoUpdate.UpdateStatus = TangoUpdateStatuses.UpdateStarted;
db.TangoUpdates.Add(tangoUpdate);
db.SaveChanges();
_pendingUpdates.Add(new PPCPendingUpdate()
{
Token = response.NotifyCompletedToken,
TangoUpdateGuid = tangoUpdate.Guid,
});
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public MachineUpdateCompletedResponse NotifyUpdateCompleted(MachineUpdateCompletedRequest request)
{
var pendingUpdate = _pendingUpdates.SingleOrDefault(x => x.Token == request.Token);
if (pendingUpdate != null)
{
_pendingUpdates.Remove(pendingUpdate);
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var tangoUpdate = db.TangoUpdates.SingleOrDefault(x => x.Guid == pendingUpdate.TangoUpdateGuid);
if (tangoUpdate != null)
{
tangoUpdate.LastUpdated = DateTime.UtcNow;
tangoUpdate.UpdateStatus = request.Status;
tangoUpdate.EndDate = DateTime.UtcNow;
tangoUpdate.FailedReason = request.FailedReason;
tangoUpdate.FailedLog = request.FailedLog;
if (request.ReportsAboutDbCheckNoDifferences)
{
db.TangoUpdates.Remove(tangoUpdate);
}
db.SaveChanges();
}
}
}
return new MachineUpdateCompletedResponse();
}
[HttpPost]
[JwtTokenFilter]
public CheckForUpdateResponse CheckForUpdates(CheckForUpdateRequest request)
{
CheckForUpdateResponse response = new CheckForUpdateResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
if (machine == null)
{
throw new AuthenticationException("The specified serial number could not be found.");
}
response.SetupFirmware = machine.SetupFirmware;
response.SetupFPGA = machine.SetupFpga;
if (!machine.SuspendVersionUpdate)
{
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == machine.MachineVersionGuid);
var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
if (Version.Parse(latest_machine_version.Version) != Version.Parse(request.Version))
{
response.IsUpdateAvailable = true;
}
response.Version = latest_machine_version.Version;
response.FirmwareVersion = latest_machine_version.FirmwareVersion;
//Compare database
var rmls = db.Rmls.Select(x => new { x.Guid, x.LastUpdated }).ToList();
var hardwareVersions = db.HardwareVersions.Select(x => new { x.Guid, x.LastUpdated }).ToList();
var catalogs = db.ColorCatalogs.Select(x => new { x.Guid, x.LastUpdated }).ToList();
var arr = request.UsedRmlsGuids.ToArray();
var existingRml = db.Rmls.Where(x => arr.Contains(x.Guid)).Select(x => x.Guid).Distinct().ToList();
response.UsedNotExistingRmlsGuids = arr.Where(x => !existingRml.Exists(y => y == x)).ToList();
bool hasDatabaseUpdates = false;
hasDatabaseUpdates = machine.LastUpdated > request.MachineLastUpdated;
if (!hasDatabaseUpdates)
{
hasDatabaseUpdates = rmls.Exists(x => request.Rmls.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.Rmls.Exists(y => x.Guid == y.Guid));
}
if (!hasDatabaseUpdates)
{
hasDatabaseUpdates = hardwareVersions.Exists(x => request.HardwareVersions.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.HardwareVersions.Exists(y => x.Guid == y.Guid));
}
if (!hasDatabaseUpdates)
{
hasDatabaseUpdates = catalogs.Exists(x => request.Catalogs.Exists(y => x.Guid == y.Guid && x.LastUpdated > y.LastUpdated) || !request.Catalogs.Exists(y => x.Guid == y.Guid));
}
if (hasDatabaseUpdates)
{
response.IsDatabaseUpdateAvailable = true;
response.UpdateDBResponse = UpdateDB(new UpdateDBRequest() { SerialNumber = request.SerialNumber });
}
//Compare database
if (machine.ForceVersionUpdate)
{
response.IsUpdateAvailable = true;
}
}
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public UpdateDBResponse UpdateDB(UpdateDBRequest request)
{
UpdateDBResponse response = new UpdateDBResponse();
response.NotifyCompletedToken = Guid.NewGuid().ToString();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
if (machine == null)
{
throw new AuthenticationException("The specified serial number could not be found.");
}
response.PerformSchemaUpdate = machine.PerformSchemaUpdateOnDataUpdate;
DbCredentials credentials = new DbCredentials();
using (SmoManager manager = new SmoManager())
{
credentials = manager.CreateRandomLoginAndUser();
Task.Delay(TimeSpan.FromMinutes(SQL_TEMP_CREDENTIALS_EXP_MINUTS)).ContinueWith((x) =>
{
using (SmoManager m = new SmoManager())
{
m.DeleteLoginAndUser(credentials.UserName);
}
});
}
response.DataSource = new DataSource()
{
Address = MachineServiceConfig.DB_ADDRESS,
Catalog = MachineServiceConfig.DB_CATALOG,
UserName = credentials.UserName,
Password = credentials.Password,
IntegratedSecurity = false,
Type = DataSourceType.SQLServer,
};
TangoUpdate tangoUpdate = new TangoUpdate();
tangoUpdate.ApplicationVersion = request.ApplicationVersion;
tangoUpdate.FirmwareVersion = request.FirmwareVersion;
tangoUpdate.MachineGuid = machine.Guid;
tangoUpdate.StartDate = DateTime.UtcNow;
tangoUpdate.UpdateStatus = TangoUpdateStatuses.DatabaseStarted;
db.TangoUpdates.Add(tangoUpdate);
db.SaveChanges();
_pendingUpdates.Add(new PPCPendingUpdate()
{
Token = response.NotifyCompletedToken,
TangoUpdateGuid = tangoUpdate.Guid,
});
}
return response;
}
#endregion
#region Synchronization
[HttpPost]
[JwtTokenFilter]
public UploadMachineDataResponse UploadMachineData(UploadMachineDataRequest request)
{
UploadMachineDataResponse response = new UploadMachineDataResponse();
response.NotifyCompletedToken = Guid.NewGuid().ToString();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
if (machine == null)
{
throw new AuthenticationException("The specified machine could not be found.");
}
TangoUpdate tangoUpdate = new TangoUpdate();
tangoUpdate.ApplicationVersion = request.ApplicationVersion;
tangoUpdate.FirmwareVersion = request.FirmwareVersion;
tangoUpdate.MachineGuid = machine.Guid;
tangoUpdate.StartDate = DateTime.UtcNow;
tangoUpdate.UpdateStatus = TangoUpdateStatuses.SynchronizationStarted;
db.TangoUpdates.Add(tangoUpdate);
db.SaveChanges();
_pendingUpdates.Add(new PPCPendingUpdate()
{
Token = response.NotifyCompletedToken,
TangoUpdateGuid = tangoUpdate.Guid,
});
}
User machineUser = null;
try
{
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
if (machine == null)
{
throw new AuthenticationException("The specified machine could not be found.");
}
machineUser = db.Users.Include(x => x.Contact).SingleOrDefault(x => x.Contact.FirstName == machine.Name);
if (machineUser == null)
{
//No machine user then create one.
machineUser = new User();
machineUser.Email = machine.SerialNumber + "@twine-s.com";
machineUser.Password = machine.SerialNumber;
machineUser.OrganizationGuid = machine.OrganizationGuid;
machineUser.Contact = new Contact();
machineUser.Contact.Email = machineUser.Email;
machineUser.Contact.FirstName = machine.Name;
machineUser.Contact.LastName = machine.Name;
machineUser.Contact.FullName = machine.Name;
machineUser.Address = new Address();
db.Users.Add(machineUser);
db.SaveChanges();
}
}
//Insert/Replace Jobs.
foreach (var dto in request.Jobs)
{
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
try
{
var job = dto.ToObservable();
job.ID = 0;
job.UserGuid = machineUser.Guid;
job.CustomerGuid = null;
job.IsSynchronized = true;
var existingJob = db.Jobs.SingleOrDefault(x => x.Guid == job.Guid);
if (existingJob == null)
{
db.Jobs.Add(job);
db.SaveChanges();
}
else if (job.LastUpdated > existingJob.LastUpdated)
{
existingJob.Delete(db);
db.Jobs.Add(job);
db.SaveChanges();
}
}
catch (Exception ex)
{
response.FailedJobs.Add(new SynchronizationFailedEntity()
{
Guid = dto.Guid,
Reason = ex.FlattenMessage(),
});
}
}
}
//Insert JobRuns.
foreach (var dto in request.JobRuns)
{
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
try
{
var run = dto.ToObservable();
run.ID = 0;
run.IsSynchronized = true;
if (db.JobRuns.SingleOrDefault(x => x.Guid == run.Guid) == null)
{
db.JobRuns.Add(run);
db.SaveChanges();
}
}
catch (Exception ex)
{
response.FailedJobRuns.Add(new SynchronizationFailedEntity()
{
Guid = dto.Guid,
Reason = ex.FlattenMessage(),
});
}
}
}
//Insert MachineEvents.
foreach (var dto in request.MachineEvents)
{
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
try
{
var ev = dto.ToObservable();
ev.ID = 0;
ev.UserGuid = machineUser.Guid;
ev.IsSynchronized = true;
if (db.MachinesEvents.SingleOrDefault(x => x.Guid == ev.Guid) == null)
{
db.MachinesEvents.Add(ev);
db.SaveChanges();
}
}
catch (Exception ex)
{
response.FailedMachineEvents.Add(new SynchronizationFailedEntity()
{
Guid = dto.Guid,
Reason = ex.FlattenMessage(),
});
}
}
}
//Insert TangoUpdates.
foreach (var dto in request.OfflineUpdates)
{
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
try
{
var update = dto.ToObservable();
update.ID = 0;
update.IsSynchronized = true;
if (db.TangoUpdates.SingleOrDefault(x => x.Guid == update.Guid) == null)
{
db.TangoUpdates.Add(update);
db.SaveChanges();
}
}
catch (Exception ex)
{
response.FailedOfflineUpdates.Add(new SynchronizationFailedEntity()
{
Guid = dto.Guid,
Reason = ex.FlattenMessage(),
});
}
}
}
}
catch (Exception ex)
{
NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
{
Status = TangoUpdateStatuses.SynchronizationFailed,
FailedReason = ex.FlattenMessage(),
FailedLog = ex.FlattenException(),
Token = response.NotifyCompletedToken,
});
throw ex;
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public DownloadMachineDataResponse DownloadMachineData(DownloadMachineDataRequest request)
{
DownloadMachineDataResponse response = new DownloadMachineDataResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
if (machine == null)
{
throw new AuthenticationException("The specified machine could not be found.");
}
//Send Jobs
if (request.RequestJobs)
{
var jobs = new JobsCollectionBuilder(db).Set(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(request.MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildList();
foreach (var job in jobs)
{
JobDTO dto = JobDTO.FromObservable(job);
response.Jobs.Add(dto);
}
}
//Send Job Runs
if (request.RequestJobRuns)
{
var jobRuns = db.JobRuns.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToList();
foreach (var jobRun in jobRuns)
{
JobRunDTO dto = JobRunDTO.FromObservable(jobRun);
response.JobRuns.Add(dto);
}
}
//Send Machine Events
if (request.RequestMachineEvents)
{
var machineEvents = db.MachinesEvents.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToList();
foreach (var machineEvent in machineEvents)
{
MachinesEventDTO dto = MachinesEventDTO.FromObservable(machineEvent);
response.MachineEvents.Add(dto);
}
}
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public NotifyMachineDataDownloadCompletedResponse NotifyMachineDataDownloadCompleted(NotifyMachineDataDownloadCompletedRequest request)
{
var response = new NotifyMachineDataDownloadCompletedResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var machine = db.Machines.SingleOrDefault(x => x.Guid == RequestToken.Object.MachineGuid);
if (machine == null)
{
throw new AuthenticationException("The specified machine could not be found.");
}
if (request.SynchronizedJobs.Count > 0)
{
db.Database.ExecuteSqlCommand($"UPDATE JOBS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobs.Select(x => "'" + x + "'"))});");
}
if (request.SynchronizedJobRuns.Count > 0)
{
db.Database.ExecuteSqlCommand($"UPDATE JOB_RUNS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedJobRuns.Select(x => "'" + x + "'"))});");
}
if (request.SynchronizedMachineEvents.Count > 0)
{
db.Database.ExecuteSqlCommand($"UPDATE MACHINES_EVENTS SET IS_SYNCHRONIZED = 1 WHERE GUID IN ({String.Join(",", request.SynchronizedMachineEvents.Select(x => "'" + x + "'"))});");
}
}
return response;
}
#endregion
#region Version Upload
[HttpPost]
public LatestVersionResponse GetLatestVersion(LatestVersionRequest request)
{
LatestVersionResponse response = new LatestVersionResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
var versions = db.TangoVersions.Where(x => x.MachineVersionGuid == request.MachineVersionGuid).ToList();
if (versions.Count == 0)
{
return new LatestVersionResponse()
{
Version = "0.0.0.0",
};
}
response.Version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault().Version;
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public UploadVersionResponse UploadVersion(UploadVersionRequest request)
{
UploadVersionResponse response = new UploadVersionResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
//Load relations first...
db.Roles.ToList();
db.Permissions.ToList();
db.UsersRoles.ToList();
db.RolesPermissions.ToList();
var user_guid = RequestToken.Object.UserGuid;
var user = new UserBuilder(db).Set(user_guid).WithRolesAndPermissions().Build();
if (user != null && user.HasPermission(Permissions.PublishPPCVersions))
{
var versions = db.TangoVersions.ToList().Where(x => x.MachineVersionGuid == request.MachineVersionGuid).OrderByDescending(x => Version.Parse(x.Version)).ToList();
var machine_version = db.MachineVersions.SingleOrDefault(x => x.Guid == request.MachineVersionGuid);
TangoVersion latestVersion = new TangoVersion();
latestVersion.Version = "0.0.0.0";
if (versions.Count > 0)
{
latestVersion = versions.FirstOrDefault();
}
Version local_version = Version.Parse(request.Version);
if (local_version > Version.Parse(latestVersion.Version))
{
String newVersionFileName = $"{machine_version.Name} - Tango Version {local_version.ToString()}.tup";
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER);
var blob = container.CreateEmptyBlob(newVersionFileName);
response.Token = Guid.NewGuid().ToString();
response.BlobAddress = blob.GenerateWriteSignature(TimeSpan.FromMinutes(30));
PPCPendingUpload pending_upload = new PPCPendingUpload()
{
UserGuid = user.Guid,
Comments = request.Comments,
Token = response.Token,
Version = request.Version,
BlobName = blob.Name,
MachineVersionGuid = request.MachineVersionGuid,
FirmwareVersion = request.FirmwareVersion,
};
if (request.WithInstaller)
{
String installerVersionFileName = Path.ChangeExtension(newVersionFileName, ".exe");
var installerBlob = container.CreateEmptyBlob(installerVersionFileName);
response.InstallerBlobAddress = installerBlob.GenerateWriteSignature(TimeSpan.FromMinutes(30));
pending_upload.InstallerBlobName = installerBlob.Name;
}
_pendingUploads.Add(pending_upload);
}
else
{
throw new ArgumentException("New version must be greater than latest version.");
}
}
else
{
throw new AuthenticationException("Invalid user credentials.");
}
}
return response;
}
[HttpPost]
[JwtTokenFilter]
public UploadCompletedResponse NotifyVersionUploadCompleted(UploadCompletedRequest request)
{
PPCPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.Token);
if (upload != null)
{
_pendingUploads.RemoveAll(x => x.Token == upload.Token);
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
db.TangoVersions.Add(new TangoVersion()
{
Comments = upload.Comments,
BlobName = upload.BlobName,
InstallerBlobName = upload.InstallerBlobName,
UserGuid = upload.UserGuid,
Version = upload.Version,
MachineVersionGuid = upload.MachineVersionGuid,
FirmwareVersion = upload.FirmwareVersion,
});
db.SaveChanges();
}
return new UploadCompletedResponse();
}
else
{
throw new AuthenticationException("Invalid upload token.");
}
}
[HttpPost]
public MachineVersionsResponse GetMachineVersions(MachineVersionsRequest request)
{
using (var db = ObservablesContextHelper.CreateContext())
{
return new MachineVersionsResponse()
{
MachineVersions = db.MachineVersions.ToList().Select(x => MachineVersionDTO.FromObservable(x)).ToList(),
};
}
}
[HttpPost]
public LoginResponse Login(LoginRequest request)
{
LoginResponse response = new LoginResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
if (request.Mode == LoginMode.User)
{
var authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password);
if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email))
{
throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment.");
}
BasicHashGenerator hash = new BasicHashGenerator();
String pass = hash.Encrypt(request.Password);
var user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && x.Password == pass).Build();
if (user == null)
{
throw new AuthenticationException("Domain user found but the database entry validation failed.");
}
response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
{
Mode = LoginMode.User,
UserGuid = user.Guid,
}).AccessToken;
}
else if (request.Mode == LoginMode.Machine)
{
var machine = db.Machines.SingleOrDefault(x => x.SerialNumber == request.SerialNumber);
if (machine == null)
{
throw new AuthenticationException("Invalid serial number.");
}
response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
{
Mode = LoginMode.Machine,
MachineGuid = machine.Guid,
}).AccessToken;
}
}
return response;
}
#endregion
}
}