mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
More updates to HDFS Manage Access dialog (#7611)
* Add display property to ModelView components * Update DisplayType property in sqlops as well * More updates to HDFS Manage Access dialog * More updates to HDFS Manage Access dialog
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" width="24" height="24">
|
||||
<path d="M1792 384h-128v1472q0 40-15 75t-41 61-61 41-75 15H448q-40 0-75-15t-61-41-41-61-15-75V384H128V256h512V128q0-27 10-50t27-40 41-28 50-10h384q27 0 50 10t40 27 28 41 10 50v128h512v128zM768 256h384V128H768v128zm768 128H384v1472q0 26 19 45t45 19h1024q26 0 45-19t19-45V384zM768 1664H640V640h128v1024zm256 0H896V640h128v1024zm256 0h-128V640h128v1024z" />
|
||||
</svg>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M14 3H13V14.5C13 14.7083 12.9609 14.9036 12.8828 15.0859C12.8047 15.2682 12.6979 15.4271 12.5625 15.5625C12.4271 15.6979 12.2682 15.8047 12.0859 15.8828C11.9036 15.9609 11.7083 16 11.5 16H3.5C3.29167 16 3.09635 15.9609 2.91406 15.8828C2.73177 15.8047 2.57292 15.6979 2.4375 15.5625C2.30208 15.4271 2.19531 15.2682 2.11719 15.0859C2.03906 14.9036 2 14.7083 2 14.5V3H1V2H5V1C5 0.859375 5.02604 0.729167 5.07812 0.609375C5.13021 0.489583 5.20052 0.385417 5.28906 0.296875C5.38281 0.203125 5.48958 0.130208 5.60938 0.078125C5.72917 0.0260417 5.85938 0 6 0H9C9.14062 0 9.27083 0.0260417 9.39062 0.078125C9.51042 0.130208 9.61458 0.203125 9.70312 0.296875C9.79688 0.385417 9.86979 0.489583 9.92188 0.609375C9.97396 0.729167 10 0.859375 10 1V2H14V3ZM6 2H9V1H6V2ZM12 3H3V14.5C3 14.6354 3.04948 14.7526 3.14844 14.8516C3.2474 14.9505 3.36458 15 3.5 15H11.5C11.6354 15 11.7526 14.9505 11.8516 14.8516C11.9505 14.7526 12 14.6354 12 14.5V3ZM6 13H5V5H6V13ZM8 13H7V5H8V13ZM10 13H9V5H10V13Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 451 B After Width: | Height: | Size: 1.2 KiB |
10
extensions/mssql/resources/dark/group_inverse.svg
Normal file
10
extensions/mssql/resources/dark/group_inverse.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M12.7812 5.41406C13.1198 5.58594 13.4245 5.79948 13.6953 6.05469C13.9714 6.30469 14.2057 6.58594 14.3984 6.89844C14.5911 7.20573 14.7396 7.53906 14.8438 7.89844C14.9479 8.2526 15 8.61979 15 9H14C14 8.58854 13.9193 8.20052 13.7578 7.83594C13.6016 7.47135 13.388 7.15365 13.1172 6.88281C12.8464 6.61198 12.5286 6.39844 12.1641 6.24219C11.7995 6.08073 11.4115 6 11 6C10.5885 6 10.2005 6.08073 9.83594 6.24219C9.47135 6.39844 9.15365 6.61198 8.88281 6.88281C8.61198 7.15365 8.39583 7.47135 8.23438 7.83594C8.07812 8.20052 8 8.58854 8 9C8 9.47396 7.89062 9.92448 7.67188 10.3516C7.45833 10.7786 7.16146 11.1328 6.78125 11.4141C7.11979 11.5859 7.42448 11.7995 7.69531 12.0547C7.97135 12.3047 8.20573 12.5859 8.39844 12.8984C8.59115 13.2057 8.73958 13.5391 8.84375 13.8984C8.94792 14.2526 9 14.6198 9 15H8C8 14.5885 7.91927 14.2005 7.75781 13.8359C7.60156 13.4714 7.38802 13.1536 7.11719 12.8828C6.84635 12.612 6.52865 12.3984 6.16406 12.2422C5.79948 12.0807 5.41146 12 5 12C4.58854 12 4.20052 12.0807 3.83594 12.2422C3.47135 12.3984 3.15365 12.612 2.88281 12.8828C2.61198 13.1536 2.39583 13.4714 2.23438 13.8359C2.07812 14.2005 2 14.5885 2 15H1C1 14.6198 1.05208 14.2526 1.15625 13.8984C1.26042 13.5391 1.40885 13.2057 1.60156 12.8984C1.79427 12.5859 2.02604 12.3047 2.29688 12.0547C2.57292 11.7995 2.88021 11.5859 3.21875 11.4141C2.83854 11.1328 2.53906 10.7786 2.32031 10.3516C2.10677 9.92448 2 9.47396 2 9C2 8.58854 2.07812 8.20052 2.23438 7.83594C2.39583 7.47135 2.61198 7.15365 2.88281 6.88281C3.15365 6.61198 3.47135 6.39844 3.83594 6.24219C4.20052 6.08073 4.58854 6 5 6C5.47396 6 5.92448 6.10938 6.35156 6.32812C6.77865 6.54167 7.13281 6.83854 7.41406 7.21875C7.61198 6.82812 7.86458 6.47917 8.17188 6.17188C8.47917 5.86458 8.82812 5.61198 9.21875 5.41406C8.83854 5.13281 8.53906 4.77865 8.32031 4.35156C8.10677 3.92448 8 3.47396 8 3C8 2.58854 8.07812 2.20052 8.23438 1.83594C8.39583 1.47135 8.61198 1.15365 8.88281 0.882812C9.15365 0.611979 9.47135 0.398438 9.83594 0.242188C10.2005 0.0807292 10.5885 0 11 0C11.4115 0 11.7995 0.0807292 12.1641 0.242188C12.5286 0.398438 12.8464 0.611979 13.1172 0.882812C13.388 1.15365 13.6016 1.47135 13.7578 1.83594C13.9193 2.20052 14 2.58854 14 3C14 3.47396 13.8906 3.92448 13.6719 4.35156C13.4583 4.77865 13.1615 5.13281 12.7812 5.41406ZM5 11C5.27083 11 5.52865 10.9479 5.77344 10.8438C6.01823 10.7344 6.22917 10.5911 6.40625 10.4141C6.58854 10.2318 6.73177 10.0208 6.83594 9.78125C6.94531 9.53646 7 9.27604 7 9C7 8.72917 6.94531 8.47135 6.83594 8.22656C6.73177 7.98177 6.58854 7.77083 6.40625 7.59375C6.22917 7.41146 6.01823 7.26823 5.77344 7.16406C5.52865 7.05469 5.27083 7 5 7C4.72396 7 4.46354 7.05469 4.21875 7.16406C3.97917 7.26823 3.76823 7.41146 3.58594 7.59375C3.40885 7.77083 3.26562 7.98177 3.15625 8.22656C3.05208 8.47135 3 8.72917 3 9C3 9.27604 3.05208 9.53646 3.15625 9.78125C3.26562 10.0208 3.40885 10.2318 3.58594 10.4141C3.76823 10.5911 3.97917 10.7344 4.21875 10.8438C4.46354 10.9479 4.72396 11 5 11ZM9 3C9 3.27604 9.05208 3.53646 9.15625 3.78125C9.26562 4.02083 9.40885 4.23177 9.58594 4.41406C9.76823 4.59115 9.97917 4.73438 10.2188 4.84375C10.4635 4.94792 10.724 5 11 5C11.2708 5 11.5286 4.94792 11.7734 4.84375C12.0182 4.73438 12.2292 4.59115 12.4062 4.41406C12.5885 4.23177 12.7318 4.02083 12.8359 3.78125C12.9453 3.53646 13 3.27604 13 3C13 2.72917 12.9453 2.47135 12.8359 2.22656C12.7318 1.98177 12.5885 1.77083 12.4062 1.59375C12.2292 1.41146 12.0182 1.26823 11.7734 1.16406C11.5286 1.05469 11.2708 1 11 1C10.724 1 10.4635 1.05469 10.2188 1.16406C9.97917 1.26823 9.76823 1.41146 9.58594 1.59375C9.40885 1.77083 9.26562 1.98177 9.15625 2.22656C9.05208 2.47135 9 2.72917 9 3Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
10
extensions/mssql/resources/dark/user_inverse.svg
Normal file
10
extensions/mssql/resources/dark/user_inverse.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M10.3906 9.39844C11.099 9.64323 11.737 9.98698 12.3047 10.4297C12.8776 10.8672 13.362 11.375 13.7578 11.9531C14.1589 12.5312 14.4661 13.1641 14.6797 13.8516C14.8932 14.5391 15 15.2552 15 16H14C14 15.1458 13.8464 14.3542 13.5391 13.625C13.237 12.8906 12.8177 12.2552 12.2812 11.7188C11.7448 11.1823 11.1094 10.763 10.375 10.4609C9.64583 10.1536 8.85417 10 8 10C7.44271 10 6.90625 10.0703 6.39062 10.2109C5.875 10.3516 5.39323 10.5521 4.94531 10.8125C4.5026 11.0677 4.09896 11.3776 3.73438 11.7422C3.375 12.1016 3.0651 12.5052 2.80469 12.9531C2.54948 13.3958 2.35156 13.875 2.21094 14.3906C2.07031 14.9062 2 15.4427 2 16H1C1 15.25 1.10938 14.5339 1.32812 13.8516C1.54688 13.1641 1.85677 12.5339 2.25781 11.9609C2.65885 11.388 3.14323 10.8828 3.71094 10.4453C4.28385 10.0078 4.92188 9.66146 5.625 9.40625C5.21875 9.1875 4.85417 8.92188 4.53125 8.60938C4.20833 8.29688 3.93229 7.95052 3.70312 7.57031C3.47917 7.1849 3.30469 6.77604 3.17969 6.34375C3.0599 5.90625 3 5.45833 3 5C3 4.30729 3.13021 3.65885 3.39062 3.05469C3.65104 2.44531 4.00781 1.91406 4.46094 1.46094C4.91406 1.00781 5.44271 0.651042 6.04688 0.390625C6.65625 0.130208 7.30729 0 8 0C8.69271 0 9.34115 0.130208 9.94531 0.390625C10.5547 0.651042 11.0859 1.00781 11.5391 1.46094C11.9922 1.91406 12.349 2.44531 12.6094 3.05469C12.8698 3.65885 13 4.30729 13 5C13 5.45833 12.9375 5.90365 12.8125 6.33594C12.6927 6.76823 12.5182 7.17448 12.2891 7.55469C12.0651 7.9349 11.7917 8.28385 11.4688 8.60156C11.151 8.91406 10.7917 9.17969 10.3906 9.39844ZM4 5C4 5.55208 4.10417 6.07031 4.3125 6.55469C4.52604 7.03906 4.8125 7.46354 5.17188 7.82812C5.53646 8.1875 5.96094 8.47396 6.44531 8.6875C6.92969 8.89583 7.44792 9 8 9C8.55208 9 9.07031 8.89583 9.55469 8.6875C10.0391 8.47396 10.4609 8.1875 10.8203 7.82812C11.1849 7.46354 11.4714 7.03906 11.6797 6.55469C11.8932 6.07031 12 5.55208 12 5C12 4.44792 11.8932 3.92969 11.6797 3.44531C11.4714 2.96094 11.1849 2.53906 10.8203 2.17969C10.4609 1.8151 10.0391 1.52865 9.55469 1.32031C9.07031 1.10677 8.55208 1 8 1C7.44792 1 6.92969 1.10677 6.44531 1.32031C5.96094 1.52865 5.53646 1.8151 5.17188 2.17969C4.8125 2.53906 4.52604 2.96094 4.3125 3.44531C4.10417 3.92969 4 4.44792 4 5Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
10
extensions/mssql/resources/light/group.svg
Normal file
10
extensions/mssql/resources/light/group.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M12.7812 5.41406C13.1198 5.58594 13.4245 5.79948 13.6953 6.05469C13.9714 6.30469 14.2057 6.58594 14.3984 6.89844C14.5911 7.20573 14.7396 7.53906 14.8438 7.89844C14.9479 8.2526 15 8.61979 15 9H14C14 8.58854 13.9193 8.20052 13.7578 7.83594C13.6016 7.47135 13.388 7.15365 13.1172 6.88281C12.8464 6.61198 12.5286 6.39844 12.1641 6.24219C11.7995 6.08073 11.4115 6 11 6C10.5885 6 10.2005 6.08073 9.83594 6.24219C9.47135 6.39844 9.15365 6.61198 8.88281 6.88281C8.61198 7.15365 8.39583 7.47135 8.23438 7.83594C8.07812 8.20052 8 8.58854 8 9C8 9.47396 7.89062 9.92448 7.67188 10.3516C7.45833 10.7786 7.16146 11.1328 6.78125 11.4141C7.11979 11.5859 7.42448 11.7995 7.69531 12.0547C7.97135 12.3047 8.20573 12.5859 8.39844 12.8984C8.59115 13.2057 8.73958 13.5391 8.84375 13.8984C8.94792 14.2526 9 14.6198 9 15H8C8 14.5885 7.91927 14.2005 7.75781 13.8359C7.60156 13.4714 7.38802 13.1536 7.11719 12.8828C6.84635 12.612 6.52865 12.3984 6.16406 12.2422C5.79948 12.0807 5.41146 12 5 12C4.58854 12 4.20052 12.0807 3.83594 12.2422C3.47135 12.3984 3.15365 12.612 2.88281 12.8828C2.61198 13.1536 2.39583 13.4714 2.23438 13.8359C2.07812 14.2005 2 14.5885 2 15H1C1 14.6198 1.05208 14.2526 1.15625 13.8984C1.26042 13.5391 1.40885 13.2057 1.60156 12.8984C1.79427 12.5859 2.02604 12.3047 2.29688 12.0547C2.57292 11.7995 2.88021 11.5859 3.21875 11.4141C2.83854 11.1328 2.53906 10.7786 2.32031 10.3516C2.10677 9.92448 2 9.47396 2 9C2 8.58854 2.07812 8.20052 2.23438 7.83594C2.39583 7.47135 2.61198 7.15365 2.88281 6.88281C3.15365 6.61198 3.47135 6.39844 3.83594 6.24219C4.20052 6.08073 4.58854 6 5 6C5.47396 6 5.92448 6.10938 6.35156 6.32812C6.77865 6.54167 7.13281 6.83854 7.41406 7.21875C7.61198 6.82812 7.86458 6.47917 8.17188 6.17188C8.47917 5.86458 8.82812 5.61198 9.21875 5.41406C8.83854 5.13281 8.53906 4.77865 8.32031 4.35156C8.10677 3.92448 8 3.47396 8 3C8 2.58854 8.07812 2.20052 8.23438 1.83594C8.39583 1.47135 8.61198 1.15365 8.88281 0.882812C9.15365 0.611979 9.47135 0.398438 9.83594 0.242188C10.2005 0.0807292 10.5885 0 11 0C11.4115 0 11.7995 0.0807292 12.1641 0.242188C12.5286 0.398438 12.8464 0.611979 13.1172 0.882812C13.388 1.15365 13.6016 1.47135 13.7578 1.83594C13.9193 2.20052 14 2.58854 14 3C14 3.47396 13.8906 3.92448 13.6719 4.35156C13.4583 4.77865 13.1615 5.13281 12.7812 5.41406ZM5 11C5.27083 11 5.52865 10.9479 5.77344 10.8438C6.01823 10.7344 6.22917 10.5911 6.40625 10.4141C6.58854 10.2318 6.73177 10.0208 6.83594 9.78125C6.94531 9.53646 7 9.27604 7 9C7 8.72917 6.94531 8.47135 6.83594 8.22656C6.73177 7.98177 6.58854 7.77083 6.40625 7.59375C6.22917 7.41146 6.01823 7.26823 5.77344 7.16406C5.52865 7.05469 5.27083 7 5 7C4.72396 7 4.46354 7.05469 4.21875 7.16406C3.97917 7.26823 3.76823 7.41146 3.58594 7.59375C3.40885 7.77083 3.26562 7.98177 3.15625 8.22656C3.05208 8.47135 3 8.72917 3 9C3 9.27604 3.05208 9.53646 3.15625 9.78125C3.26562 10.0208 3.40885 10.2318 3.58594 10.4141C3.76823 10.5911 3.97917 10.7344 4.21875 10.8438C4.46354 10.9479 4.72396 11 5 11ZM9 3C9 3.27604 9.05208 3.53646 9.15625 3.78125C9.26562 4.02083 9.40885 4.23177 9.58594 4.41406C9.76823 4.59115 9.97917 4.73438 10.2188 4.84375C10.4635 4.94792 10.724 5 11 5C11.2708 5 11.5286 4.94792 11.7734 4.84375C12.0182 4.73438 12.2292 4.59115 12.4062 4.41406C12.5885 4.23177 12.7318 4.02083 12.8359 3.78125C12.9453 3.53646 13 3.27604 13 3C13 2.72917 12.9453 2.47135 12.8359 2.22656C12.7318 1.98177 12.5885 1.77083 12.4062 1.59375C12.2292 1.41146 12.0182 1.26823 11.7734 1.16406C11.5286 1.05469 11.2708 1 11 1C10.724 1 10.4635 1.05469 10.2188 1.16406C9.97917 1.26823 9.76823 1.41146 9.58594 1.59375C9.40885 1.77083 9.26562 1.98177 9.15625 2.22656C9.05208 2.47135 9 2.72917 9 3Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
10
extensions/mssql/resources/light/user.svg
Normal file
10
extensions/mssql/resources/light/user.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M10.3906 9.39844C11.099 9.64323 11.737 9.98698 12.3047 10.4297C12.8776 10.8672 13.362 11.375 13.7578 11.9531C14.1589 12.5312 14.4661 13.1641 14.6797 13.8516C14.8932 14.5391 15 15.2552 15 16H14C14 15.1458 13.8464 14.3542 13.5391 13.625C13.237 12.8906 12.8177 12.2552 12.2812 11.7188C11.7448 11.1823 11.1094 10.763 10.375 10.4609C9.64583 10.1536 8.85417 10 8 10C7.44271 10 6.90625 10.0703 6.39062 10.2109C5.875 10.3516 5.39323 10.5521 4.94531 10.8125C4.5026 11.0677 4.09896 11.3776 3.73438 11.7422C3.375 12.1016 3.0651 12.5052 2.80469 12.9531C2.54948 13.3958 2.35156 13.875 2.21094 14.3906C2.07031 14.9062 2 15.4427 2 16H1C1 15.25 1.10938 14.5339 1.32812 13.8516C1.54688 13.1641 1.85677 12.5339 2.25781 11.9609C2.65885 11.388 3.14323 10.8828 3.71094 10.4453C4.28385 10.0078 4.92188 9.66146 5.625 9.40625C5.21875 9.1875 4.85417 8.92188 4.53125 8.60938C4.20833 8.29688 3.93229 7.95052 3.70312 7.57031C3.47917 7.1849 3.30469 6.77604 3.17969 6.34375C3.0599 5.90625 3 5.45833 3 5C3 4.30729 3.13021 3.65885 3.39062 3.05469C3.65104 2.44531 4.00781 1.91406 4.46094 1.46094C4.91406 1.00781 5.44271 0.651042 6.04688 0.390625C6.65625 0.130208 7.30729 0 8 0C8.69271 0 9.34115 0.130208 9.94531 0.390625C10.5547 0.651042 11.0859 1.00781 11.5391 1.46094C11.9922 1.91406 12.349 2.44531 12.6094 3.05469C12.8698 3.65885 13 4.30729 13 5C13 5.45833 12.9375 5.90365 12.8125 6.33594C12.6927 6.76823 12.5182 7.17448 12.2891 7.55469C12.0651 7.9349 11.7917 8.28385 11.4688 8.60156C11.151 8.91406 10.7917 9.17969 10.3906 9.39844ZM4 5C4 5.55208 4.10417 6.07031 4.3125 6.55469C4.52604 7.03906 4.8125 7.46354 5.17188 7.82812C5.53646 8.1875 5.96094 8.47396 6.44531 8.6875C6.92969 8.89583 7.44792 9 8 9C8.55208 9 9.07031 8.89583 9.55469 8.6875C10.0391 8.47396 10.4609 8.1875 10.8203 7.82812C11.1849 7.46354 11.4714 7.03906 11.6797 6.55469C11.8932 6.07031 12 5.55208 12 5C12 4.44792 11.8932 3.92969 11.6797 3.44531C11.4714 2.96094 11.1849 2.53906 10.8203 2.17969C10.4609 1.8151 10.0391 1.52865 9.55469 1.32031C9.07031 1.10677 8.55208 1 8 1C7.44792 1 6.92969 1.10677 6.44531 1.32031C5.96094 1.52865 5.53646 1.8151 5.17188 2.17969C4.8125 2.53906 4.52604 2.96094 4.3125 3.44531C4.10417 3.92969 4 4.44792 4 5Z" fill="#333333"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -3,38 +3,44 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IconPathHelper, IconPath } from '../iconHelper';
|
||||
|
||||
/**
|
||||
* The parsed result from calling getAclStatus on the controller
|
||||
* The permission status of an HDFS path - this consists of :
|
||||
* - The sticky bit for that path
|
||||
* - The permission bits for the owner, group and other
|
||||
* - (Optional) Set of additional ACL entries on this path
|
||||
*/
|
||||
export interface IAclStatus {
|
||||
export class PermissionStatus {
|
||||
/**
|
||||
* The ACL entries defined for the object
|
||||
*/
|
||||
entries: AclEntry[];
|
||||
/**
|
||||
* The ACL entry object for the owner permissions
|
||||
*/
|
||||
owner: AclEntry;
|
||||
/**
|
||||
* The ACL entry object for the group permissions
|
||||
*/
|
||||
group: AclEntry;
|
||||
/**
|
||||
* The ACL entry object for the other permissions
|
||||
*/
|
||||
other: AclEntry;
|
||||
/**
|
||||
* The sticky bit status for the object. If true the owner/root are
|
||||
*
|
||||
* @param owner The ACL entry object for the owner permissions
|
||||
* @param group The ACL entry object for the group permissions
|
||||
* @param other The ACL entry object for the other permissions
|
||||
* @param stickyBit The sticky bit status for the object. If true the owner/root are
|
||||
* the only ones who can delete the resource or its contents (if a folder)
|
||||
* @param aclEntries The ACL entries defined for the object
|
||||
*/
|
||||
stickyBit: boolean;
|
||||
constructor(public owner: AclEntry, public group: AclEntry, public other: AclEntry, public stickyBit: boolean, public aclEntries: AclEntry[]) { }
|
||||
|
||||
/**
|
||||
* The permission octal for the path in the form [#]### with each # mapping to :
|
||||
* 0 (optional) - The sticky bit (1 or 0)
|
||||
* 1 - The owner permission digit
|
||||
* 2 - The group permission digit
|
||||
* 3 - The other permission digit
|
||||
* @see AclEntryPermission for more information on the permission digits
|
||||
*/
|
||||
public get permissionOctal(): string {
|
||||
return `${this.stickyBit ? '1' : ''}${this.owner.permissionDigit}${this.group.permissionDigit}${this.other.permissionDigit}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of an ACL entry. Corresponds to the first (or second if a scope is present) field of
|
||||
* an ACL entry - e.g. user:bob:rwx (user) or default:group::r-- (group)
|
||||
*/
|
||||
export enum AclEntryType {
|
||||
export enum AclType {
|
||||
/**
|
||||
* An ACL entry applied to a specific user.
|
||||
*/
|
||||
@@ -58,7 +64,7 @@ export enum AclEntryType {
|
||||
* Typically this value is represented as a 3 digit octal - e.g. 740 - where the first digit is the owner, the second
|
||||
* the group and the third other. @see parseAclPermissionFromOctal
|
||||
*/
|
||||
export enum AclPermissionType {
|
||||
export enum PermissionType {
|
||||
owner = 'owner',
|
||||
group = 'group',
|
||||
other = 'other'
|
||||
@@ -92,6 +98,14 @@ export class AclEntryPermission {
|
||||
public toString() {
|
||||
return `${this.read ? 'r' : '-'}${this.write ? 'w' : '-'}${this.execute ? 'x' : '-'}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the digit for a permission octal for this permission. This digit is a value
|
||||
* between 0 and 7 inclusive, which is a bitwise OR the permission flags (r/w/x).
|
||||
*/
|
||||
public get permissionDigit(): number {
|
||||
return (this.read ? 4 : 0) + (this.write ? 2 : 0) + (this.execute ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,12 +137,19 @@ function parseAclPermission(permissionString: string): AclEntryPermission {
|
||||
export class AclEntry {
|
||||
constructor(
|
||||
public readonly scope: AclEntryScope,
|
||||
public readonly type: AclEntryType | AclPermissionType,
|
||||
public readonly type: AclType | PermissionType,
|
||||
public readonly name: string,
|
||||
public readonly displayName: string,
|
||||
public readonly permission: AclEntryPermission,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Gets the octal number representing the permission for this entry. This digit is a value
|
||||
* between 0 and 7 inclusive, which is a bitwise OR the permission flags (r/w/x).
|
||||
*/
|
||||
public get permissionDigit(): number {
|
||||
return this.permission.permissionDigit;
|
||||
}
|
||||
/**
|
||||
* Returns the string representation of the ACL Entry in the form [SCOPE:]TYPE:NAME:PERMISSION.
|
||||
* Note that SCOPE is only displayed if it's default - access is implied if there is no scope
|
||||
@@ -163,22 +184,22 @@ export class AclEntry {
|
||||
* Maps the possible entry types into their corresponding values for using in an ACL string
|
||||
* @param type The type to convert
|
||||
*/
|
||||
function getAclEntryType(type: AclEntryType | AclPermissionType): AclEntryType {
|
||||
function getAclEntryType(type: AclType | PermissionType): AclType {
|
||||
// We only need to map AclPermissionType - AclEntryType is already the
|
||||
// correct values we're mapping to.
|
||||
if (type in AclPermissionType) {
|
||||
if (type in PermissionType) {
|
||||
switch (type) {
|
||||
case AclPermissionType.owner:
|
||||
return AclEntryType.user;
|
||||
case AclPermissionType.group:
|
||||
return AclEntryType.group;
|
||||
case AclPermissionType.other:
|
||||
return AclEntryType.other;
|
||||
case PermissionType.owner:
|
||||
return AclType.user;
|
||||
case PermissionType.group:
|
||||
return AclType.group;
|
||||
case PermissionType.other:
|
||||
return AclType.other;
|
||||
default:
|
||||
throw new Error(`Unknown AclPermissionType : ${type}`);
|
||||
}
|
||||
}
|
||||
return <AclEntryType>type;
|
||||
return <AclType>type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,19 +234,19 @@ export function parseAclEntry(aclString: string): AclEntry {
|
||||
const parts: string[] = aclString.split(':');
|
||||
let i = 0;
|
||||
const scope: AclEntryScope = parts.length === 4 && parts[i++] === 'default' ? AclEntryScope.default : AclEntryScope.access;
|
||||
let type: AclEntryType;
|
||||
let type: AclType;
|
||||
switch (parts[i++]) {
|
||||
case 'user':
|
||||
type = AclEntryType.user;
|
||||
type = AclType.user;
|
||||
break;
|
||||
case 'group':
|
||||
type = AclEntryType.group;
|
||||
type = AclType.group;
|
||||
break;
|
||||
case 'mask':
|
||||
type = AclEntryType.mask;
|
||||
type = AclType.mask;
|
||||
break;
|
||||
case 'other':
|
||||
type = AclEntryType.other;
|
||||
type = AclType.other;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown ACL Entry type ${parts[i - 1]}`);
|
||||
@@ -269,3 +290,16 @@ export function parseAclPermissionFromOctal(octal: string): { sticky: boolean, o
|
||||
other: new AclEntryPermission((otherPermissionDigit & 4) === 4, (otherPermissionDigit & 2) === 2, (otherPermissionDigit & 1) === 1)
|
||||
};
|
||||
}
|
||||
|
||||
export function getImageForType(type: AclType | PermissionType): IconPath {
|
||||
switch (type) {
|
||||
case AclType.user:
|
||||
case PermissionType.owner:
|
||||
return IconPathHelper.user;
|
||||
case AclType.group:
|
||||
case PermissionType.group:
|
||||
case PermissionType.other:
|
||||
return IconPathHelper.group;
|
||||
}
|
||||
return { dark: '', light: '' };
|
||||
}
|
||||
|
||||
85
extensions/mssql/src/hdfs/fileStatus.ts
Normal file
85
extensions/mssql/src/hdfs/fileStatus.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export enum HdfsFileType {
|
||||
File = 'File',
|
||||
Directory = 'Directory',
|
||||
Symlink = 'Symlink'
|
||||
}
|
||||
|
||||
export class FileStatus {
|
||||
/**
|
||||
*
|
||||
* @param owner The ACL entry object for the owner permissions
|
||||
* @param group The ACL entry object for the group permissions
|
||||
* @param other The ACL entry object for the other permissions
|
||||
* @param stickyBit The sticky bit status for the object. If true the owner/root are
|
||||
* the only ones who can delete the resource or its contents (if a folder)
|
||||
* @param aclEntries The ACL entries defined for the object
|
||||
*/
|
||||
constructor(
|
||||
/**
|
||||
* Access time for the file
|
||||
*/
|
||||
public readonly accessTime: string,
|
||||
/**
|
||||
* The block size of a file.
|
||||
*/
|
||||
public readonly blockSize: string,
|
||||
/**
|
||||
* The group owner.
|
||||
*/
|
||||
public readonly group: string,
|
||||
/**
|
||||
* The number of bytes in a file. (0 for directories)
|
||||
*/
|
||||
public readonly length: string,
|
||||
/**
|
||||
* The modification time.
|
||||
*/
|
||||
public readonly modificationTime: string,
|
||||
/**
|
||||
* The user who is the owner.
|
||||
*/
|
||||
public readonly owner: string,
|
||||
/**
|
||||
* The path suffix.
|
||||
*/
|
||||
public readonly pathSuffix: string,
|
||||
/**
|
||||
* The permission represented as a octal string.
|
||||
*/
|
||||
public readonly permission: string,
|
||||
/**
|
||||
* The number of replication of a file.
|
||||
*/
|
||||
public readonly replication: string,
|
||||
/**
|
||||
* Whether a directory is snapshot enabled or not
|
||||
*/
|
||||
public readonly snapshotEnabled: string,
|
||||
/**
|
||||
* The type of the path object.
|
||||
*/
|
||||
public readonly type: HdfsFileType
|
||||
) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a fileType string into the corresponding @see HdfsFileType
|
||||
* @param fileType The fileType string to parse
|
||||
*/
|
||||
export function parseHdfsFileType(fileType: string): HdfsFileType {
|
||||
switch (fileType.toLowerCase()) {
|
||||
case 'file':
|
||||
return HdfsFileType.File;
|
||||
case 'directory':
|
||||
return HdfsFileType.Directory;
|
||||
case 'symlink':
|
||||
return HdfsFileType.Symlink;
|
||||
default:
|
||||
throw new Error(`Unknown HdfsFileType '${fileType}'`);
|
||||
}
|
||||
}
|
||||
@@ -5,23 +5,29 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { IFileSource } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { IAclStatus, AclEntry, AclEntryScope, AclEntryType, AclEntryPermission } from './aclEntry';
|
||||
import { PermissionStatus, AclEntry, AclEntryScope, AclType, AclEntryPermission } from './aclEntry';
|
||||
import { FileStatus } from './fileStatus';
|
||||
|
||||
/**
|
||||
* Model for storing the state of a specified file/folder in HDFS
|
||||
*/
|
||||
export class HdfsModel {
|
||||
|
||||
private readonly _onAclStatusUpdated = new vscode.EventEmitter<IAclStatus>();
|
||||
private readonly _onPermissionStatusUpdated = new vscode.EventEmitter<PermissionStatus>();
|
||||
/**
|
||||
* Event that's fired anytime changes are made by the model to the ACLStatus
|
||||
* Event that's fired anytime changes are made by the model to the @see PermissionStatus
|
||||
*/
|
||||
public onAclStatusUpdated = this._onAclStatusUpdated.event;
|
||||
public onPermissionStatusUpdated = this._onPermissionStatusUpdated.event;
|
||||
|
||||
/**
|
||||
* The ACL status of the file/folder
|
||||
* The @see PermissionStatus of the file/folder
|
||||
*/
|
||||
public aclStatus: IAclStatus;
|
||||
public permissionStatus: PermissionStatus;
|
||||
|
||||
/**
|
||||
* The @see FileStatus of the file/folder
|
||||
*/
|
||||
public fileStatus: FileStatus;
|
||||
|
||||
constructor(private fileSource: IFileSource, private path: string) {
|
||||
this.refresh();
|
||||
@@ -31,8 +37,10 @@ export class HdfsModel {
|
||||
* Refresh the ACL status with the current values on HDFS
|
||||
*/
|
||||
public async refresh(): Promise<void> {
|
||||
this.aclStatus = await this.fileSource.getAclStatus(this.path);
|
||||
this._onAclStatusUpdated.fire(this.aclStatus);
|
||||
[this.permissionStatus, this.fileStatus] = await Promise.all([
|
||||
this.fileSource.getAclStatus(this.path),
|
||||
this.fileSource.getFileStatus(this.path)]);
|
||||
this._onPermissionStatusUpdated.fire(this.permissionStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,18 +49,18 @@ export class HdfsModel {
|
||||
* @param name The name of the ACL Entry
|
||||
* @param type The type of ACL to create
|
||||
*/
|
||||
public createAndAddAclEntry(name: string, type: AclEntryType): void {
|
||||
if (!this.aclStatus) {
|
||||
public createAndAddAclEntry(name: string, type: AclType): void {
|
||||
if (!this.permissionStatus) {
|
||||
return;
|
||||
}
|
||||
const newEntry = new AclEntry(AclEntryScope.access, type, name, name, new AclEntryPermission(true, true, true));
|
||||
// Don't add duplicates. This also checks the owner, group and other items
|
||||
if ([this.aclStatus.owner, this.aclStatus.group, this.aclStatus.other].concat(this.aclStatus.entries).find(entry => entry.isEqual(newEntry))) {
|
||||
if ([this.permissionStatus.owner, this.permissionStatus.group, this.permissionStatus.other].concat(this.permissionStatus.aclEntries).find(entry => entry.isEqual(newEntry))) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.aclStatus.entries.push(newEntry);
|
||||
this._onAclStatusUpdated.fire(this.aclStatus);
|
||||
this.permissionStatus.aclEntries.push(newEntry);
|
||||
this._onPermissionStatusUpdated.fire(this.permissionStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,8 +68,8 @@ export class HdfsModel {
|
||||
* @param entryToDelete The entry to delete
|
||||
*/
|
||||
public deleteAclEntry(entryToDelete: AclEntry): void {
|
||||
this.aclStatus.entries = this.aclStatus.entries.filter(entry => !entry.isEqual(entryToDelete));
|
||||
this._onAclStatusUpdated.fire(this.aclStatus);
|
||||
this.permissionStatus.aclEntries = this.permissionStatus.aclEntries.filter(entry => !entry.isEqual(entryToDelete));
|
||||
this._onPermissionStatusUpdated.fire(this.permissionStatus);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +78,10 @@ export class HdfsModel {
|
||||
* permissions that shouldn't change need to still exist and have the same values.
|
||||
* @param recursive Whether to apply the changes recursively (to all sub-folders and files)
|
||||
*/
|
||||
public apply(recursive: boolean = false): Promise<void> {
|
||||
public apply(recursive: boolean = false): Promise<any> {
|
||||
// TODO Apply recursive
|
||||
return this.fileSource.setAcl(this.path, this.aclStatus.owner, this.aclStatus.group, this.aclStatus.other, this.aclStatus.entries);
|
||||
return Promise.all([
|
||||
this.fileSource.setAcl(this.path, this.permissionStatus.owner, this.permissionStatus.group, this.permissionStatus.other, this.permissionStatus.aclEntries),
|
||||
this.fileSource.setPermission(this.path, this.permissionStatus)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
import * as azdata from 'azdata';
|
||||
import { HdfsModel } from '../hdfsModel';
|
||||
import { IFileSource } from '../../objectExplorerNodeProvider/fileSources';
|
||||
import { IAclStatus, AclEntry, AclEntryType } from '../../hdfs/aclEntry';
|
||||
import { PermissionStatus, AclEntry, AclType, getImageForType } from '../../hdfs/aclEntry';
|
||||
import { cssStyles } from './uiConstants';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import { HdfsError } from '../webhdfs';
|
||||
import { ApiWrapper } from '../../apiWrapper';
|
||||
import { IconPathHelper } from '../../iconHelper';
|
||||
import { HdfsFileType } from '../fileStatus';
|
||||
|
||||
const permissionsTypeIconColumnWidth = 35;
|
||||
const permissionsNameColumnWidth = 250;
|
||||
const permissionsStickyColumnWidth = 50;
|
||||
const permissionsReadColumnWidth = 50;
|
||||
@@ -36,11 +38,13 @@ export class ManageAccessDialog {
|
||||
private addUserOrGroupInput: azdata.InputBoxComponent;
|
||||
private dialog: azdata.window.Dialog;
|
||||
|
||||
private addUserOrGroupSelectedType: AclEntryType;
|
||||
private defaultSectionComponents: azdata.Component[] = [];
|
||||
|
||||
private addUserOrGroupSelectedType: AclType;
|
||||
|
||||
constructor(private hdfsPath: string, private fileSource: IFileSource, private readonly apiWrapper: ApiWrapper) {
|
||||
this.hdfsModel = new HdfsModel(this.fileSource, this.hdfsPath);
|
||||
this.hdfsModel.onAclStatusUpdated(aclStatus => this.handleAclStatusUpdated(aclStatus));
|
||||
this.hdfsModel.onPermissionStatusUpdated(permissionStatus => this.handlePermissionStatusUpdated(permissionStatus));
|
||||
}
|
||||
|
||||
public openDialog(): void {
|
||||
@@ -123,7 +127,7 @@ export class ManageAccessDialog {
|
||||
// = Owners permissions section =
|
||||
// ==============================
|
||||
|
||||
const ownersPermissionsHeaderRow = createPermissionsHeaderRow(modelView.modelBuilder, loc.ownersHeader, true);
|
||||
const ownersPermissionsHeaderRow = this.createPermissionsHeaderRow(modelView.modelBuilder, loc.ownersHeader, true);
|
||||
contentContainer.addItem(ownersPermissionsHeaderRow, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
// Empty initially - this is going to eventually be populated with the owner/owning group permissions
|
||||
@@ -155,10 +159,10 @@ export class ManageAccessDialog {
|
||||
|
||||
const typeContainer = modelView.modelBuilder.flexContainer().withProperties({ flexFlow: 'row' }).component();
|
||||
const aclEntryTypeGroup = 'aclEntryType';
|
||||
const userTypeButton = this.createRadioButton(modelView.modelBuilder, loc.userLabel, aclEntryTypeGroup, AclEntryType.user);
|
||||
const groupTypeButton = this.createRadioButton(modelView.modelBuilder, loc.groupLabel, aclEntryTypeGroup, AclEntryType.group);
|
||||
const userTypeButton = this.createRadioButton(modelView.modelBuilder, loc.userLabel, aclEntryTypeGroup, AclType.user);
|
||||
const groupTypeButton = this.createRadioButton(modelView.modelBuilder, loc.groupLabel, aclEntryTypeGroup, AclType.group);
|
||||
userTypeButton.checked = true;
|
||||
this.addUserOrGroupSelectedType = AclEntryType.user;
|
||||
this.addUserOrGroupSelectedType = AclType.user;
|
||||
|
||||
typeContainer.addItems([userTypeButton, groupTypeButton], { flex: '0 0 auto' });
|
||||
contentContainer.addItem(typeContainer, { flex: '0 0 auto' });
|
||||
@@ -199,7 +203,7 @@ export class ManageAccessDialog {
|
||||
// = Named Users and Groups permissions header row =
|
||||
// =================================================
|
||||
|
||||
const namedUsersAndGroupsPermissionsHeaderRow = createPermissionsHeaderRow(modelView.modelBuilder, loc.namedUsersAndGroupsHeader, false);
|
||||
const namedUsersAndGroupsPermissionsHeaderRow = this.createPermissionsHeaderRow(modelView.modelBuilder, loc.namedUsersAndGroupsHeader, false);
|
||||
contentContainer.addItem(namedUsersAndGroupsPermissionsHeaderRow, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
// Empty initially - this is eventually going to be populated with the ACL entries set for this path
|
||||
@@ -209,7 +213,7 @@ export class ManageAccessDialog {
|
||||
contentContainer.addItem(this.namedUsersAndGroupsPermissionsContainer, { flex: '1', CSSStyles: { 'overflow': 'scroll', 'min-height': '200px' } });
|
||||
|
||||
this.viewInitialized = true;
|
||||
this.handleAclStatusUpdated(this.hdfsModel.aclStatus);
|
||||
this.handlePermissionStatusUpdated(this.hdfsModel.permissionStatus);
|
||||
await modelView.initializeModel(this.rootLoadingComponent);
|
||||
});
|
||||
this.dialog.content = [tab];
|
||||
@@ -218,25 +222,28 @@ export class ManageAccessDialog {
|
||||
azdata.window.openDialog(this.dialog);
|
||||
}
|
||||
|
||||
private handleAclStatusUpdated(aclStatus: IAclStatus): void {
|
||||
if (!aclStatus || !this.viewInitialized) {
|
||||
private handlePermissionStatusUpdated(permissionStatus: PermissionStatus): void {
|
||||
if (!permissionStatus || !this.viewInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update display status for headers for the Default section - you can't set Default ACLs for non-directories so we just hide that column
|
||||
this.defaultSectionComponents.forEach(component => component.display = this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? '' : 'none');
|
||||
|
||||
// Owners
|
||||
const ownerPermissionsRow = this.createOwnerPermissionsRow(this.modelBuilder, aclStatus.stickyBit, aclStatus.owner);
|
||||
const owningGroupPermissionsRow = this.createPermissionsRow(this.modelBuilder, aclStatus.group, false);
|
||||
const ownerPermissionsRow = this.createOwnerPermissionsRow(this.modelBuilder, permissionStatus);
|
||||
const owningGroupPermissionsRow = this.createPermissionsRow(this.modelBuilder, permissionStatus.group, /*includeDelete*/false);
|
||||
this.ownersPermissionsContainer.clearItems();
|
||||
this.ownersPermissionsContainer.addItems([ownerPermissionsRow, owningGroupPermissionsRow], { CSSStyles: { 'border-bottom': cssStyles.tableBorderCss, 'border-top': cssStyles.tableBorderCss, 'margin-right': '14px' } });
|
||||
|
||||
// Others
|
||||
const otherPermissionsRow = this.createPermissionsRow(this.modelBuilder, aclStatus.other, false);
|
||||
const otherPermissionsRow = this.createPermissionsRow(this.modelBuilder, permissionStatus.other, false);
|
||||
this.othersPermissionsContainer.clearItems();
|
||||
this.othersPermissionsContainer.addItem(otherPermissionsRow, { CSSStyles: { 'border-bottom': cssStyles.tableBorderCss, 'border-top': cssStyles.tableBorderCss, 'margin-right': '14px' } });
|
||||
|
||||
this.namedUsersAndGroupsPermissionsContainer.clearItems();
|
||||
// Named users and groups
|
||||
aclStatus.entries.forEach(entry => {
|
||||
permissionStatus.aclEntries.forEach(entry => {
|
||||
const namedEntryRow = this.createPermissionsRow(this.modelBuilder, entry, true);
|
||||
this.namedUsersAndGroupsPermissionsContainer.addItem(namedEntryRow, { CSSStyles: { 'border-bottom': cssStyles.tableBorderCss, 'border-top': cssStyles.tableBorderCss } });
|
||||
});
|
||||
@@ -244,7 +251,7 @@ export class ManageAccessDialog {
|
||||
this.rootLoadingComponent.loading = false;
|
||||
}
|
||||
|
||||
private createRadioButton(modelBuilder: azdata.ModelBuilder, label: string, name: string, aclEntryType: AclEntryType): azdata.RadioButtonComponent {
|
||||
private createRadioButton(modelBuilder: azdata.ModelBuilder, label: string, name: string, aclEntryType: AclType): azdata.RadioButtonComponent {
|
||||
const button = modelBuilder.radioButton().withProperties<azdata.RadioButtonProperties>({ label: label, name: name }).component();
|
||||
button.onDidClick(() => {
|
||||
this.addUserOrGroupSelectedType = aclEntryType;
|
||||
@@ -252,16 +259,33 @@ export class ManageAccessDialog {
|
||||
return button;
|
||||
}
|
||||
|
||||
private createOwnerPermissionsRow(builder: azdata.ModelBuilder, sticky: boolean, entry: AclEntry): azdata.FlexContainer {
|
||||
const row = this.createPermissionsRow(builder, entry, false);
|
||||
const stickyComponents = createCheckbox(builder, sticky, permissionsReadColumnWidth, permissionsRowHeight);
|
||||
private createOwnerPermissionsRow(builder: azdata.ModelBuilder, permissionStatus: PermissionStatus): azdata.FlexContainer {
|
||||
const row = this.createPermissionsRow(builder, permissionStatus.owner, false);
|
||||
const stickyComponents = createCheckbox(builder, permissionStatus.stickyBit, permissionsReadColumnWidth, permissionsRowHeight);
|
||||
stickyComponents.checkbox.onChanged(() => {
|
||||
permissionStatus.stickyBit = stickyComponents.checkbox.checked;
|
||||
});
|
||||
// Insert after name item but before other checkboxes
|
||||
row.insertItem(stickyComponents.container, 1, { flex: '0 0 auto' });
|
||||
row.insertItem(stickyComponents.container, 2, { flex: '0 0 auto' });
|
||||
return row;
|
||||
}
|
||||
|
||||
private createPermissionsRow(builder: azdata.ModelBuilder, entry: AclEntry, includeDelete: boolean): azdata.FlexContainer {
|
||||
const rowContainer = builder.flexContainer().withLayout({ flexFlow: 'row', height: permissionsRowHeight }).component();
|
||||
|
||||
// Icon
|
||||
const iconCell = builder.image()
|
||||
.withProperties<azdata.ImageComponentProperties>({
|
||||
iconPath: getImageForType(entry.type),
|
||||
width: permissionsTypeIconColumnWidth,
|
||||
height: permissionsRowHeight,
|
||||
iconWidth: 20,
|
||||
iconHeight: 20
|
||||
})
|
||||
.component();
|
||||
rowContainer.addItem(iconCell, { flex: '0 0 auto' });
|
||||
|
||||
// Name
|
||||
const nameCell = builder.text().withProperties({ value: entry.displayName }).component();
|
||||
rowContainer.addItem(nameCell);
|
||||
|
||||
@@ -281,31 +305,35 @@ export class ManageAccessDialog {
|
||||
|
||||
// Access - Execute
|
||||
const accessExecuteComponents = createCheckbox(builder, entry.permission.execute, permissionsExecuteColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(accessExecuteComponents.container, { flex: '0 0 auto', CSSStyles: { 'border-right': cssStyles.tableBorderCss } });
|
||||
rowContainer.addItem(accessExecuteComponents.container, { flex: '0 0 auto', CSSStyles: { 'border-right': this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? cssStyles.tableBorderCss : '' } });
|
||||
accessExecuteComponents.checkbox.onChanged(() => {
|
||||
entry.permission.execute = accessExecuteComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Default - Read
|
||||
const defaultReadComponents = createCheckbox(builder, false, permissionsReadColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultReadComponents.container, { flex: '0 0 auto' });
|
||||
defaultReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.read = defaultReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
// Only directories can set ACL defaults so we hide the column for non-directories
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
// Default - Read
|
||||
const defaultReadComponents = createCheckbox(builder, false, permissionsReadColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultReadComponents.container, { flex: '0 0 auto' });
|
||||
defaultReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.read = defaultReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
|
||||
// Default - Write
|
||||
const defaultWriteComponents = createCheckbox(builder, false, permissionsWriteColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultWriteComponents.container, { flex: '0 0 auto' });
|
||||
accessReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.write = accessReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
// Default - Write
|
||||
const defaultWriteComponents = createCheckbox(builder, false, permissionsWriteColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultWriteComponents.container, { flex: '0 0 auto' });
|
||||
accessReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.write = accessReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
|
||||
// Default - Execute
|
||||
const defaultExecuteComponents = createCheckbox(builder, false, permissionsExecuteColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultExecuteComponents.container, { flex: '0 0 auto' });
|
||||
accessReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.execute = accessReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
}
|
||||
|
||||
// Default - Execute
|
||||
const defaultExecuteComponents = createCheckbox(builder, false, permissionsExecuteColumnWidth, permissionsRowHeight);
|
||||
rowContainer.addItem(defaultExecuteComponents.container, { flex: '0 0 auto' });
|
||||
accessReadComponents.checkbox.onChanged(() => {
|
||||
// entry.permission.execute = accessReadComponents.checkbox.checked; TODO hook up default logic
|
||||
});
|
||||
|
||||
const deleteContainer = builder.flexContainer().withLayout({ width: permissionsDeleteColumnWidth, height: permissionsRowHeight }).component();
|
||||
|
||||
@@ -327,60 +355,90 @@ export class ManageAccessDialog {
|
||||
|
||||
return rowContainer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the header row for the permissions tables. This contains headers for the name, optional sticky and then read/write/execute for both
|
||||
* access and default sections.
|
||||
* @param modelBuilder The builder used to create the model components
|
||||
* @param nameColumnText The text to display for the name column
|
||||
* @param includeSticky Whether to include the sticky header
|
||||
*/
|
||||
function createPermissionsHeaderRow(modelBuilder: azdata.ModelBuilder, nameColumnText: string, includeSticky: boolean): azdata.FlexContainer {
|
||||
const rowsContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||
/**
|
||||
* Creates the header row for the permissions tables. This contains headers for the name, optional sticky and then read/write/execute for both
|
||||
* access and default sections.
|
||||
* @param modelBuilder The builder used to create the model components
|
||||
* @param nameColumnText The text to display for the name column
|
||||
* @param includeSticky Whether to include the sticky header
|
||||
*/
|
||||
private createPermissionsHeaderRow(modelBuilder: azdata.ModelBuilder, nameColumnText: string, includeSticky: boolean): azdata.FlexContainer {
|
||||
const rowsContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||
|
||||
// Section Headers
|
||||
const sectionHeaderContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row', justifyContent: 'flex-end' }).component();
|
||||
const accessSectionHeader = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.accessHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
sectionHeaderContainer.addItem(accessSectionHeader, { CSSStyles: { 'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px` } });
|
||||
const defaultSectionHeader = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.defaultHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
sectionHeaderContainer.addItem(defaultSectionHeader, { CSSStyles: { 'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px` } });
|
||||
// Delete - just used as a spacer
|
||||
const deleteSectionHeader = modelBuilder.text().component();
|
||||
sectionHeaderContainer.addItem(deleteSectionHeader, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
// Section Headers
|
||||
const sectionHeaderContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row', justifyContent: 'flex-end' }).component();
|
||||
const accessSectionHeader = modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.accessHeader,
|
||||
CSSStyles: {
|
||||
'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
}
|
||||
})
|
||||
.component();
|
||||
|
||||
rowsContainer.addItem(sectionHeaderContainer);
|
||||
sectionHeaderContainer.addItem(accessSectionHeader, { flex: '0 0 auto' });
|
||||
const defaultSectionHeader = modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.defaultHeader,
|
||||
CSSStyles: {
|
||||
'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
}
|
||||
})
|
||||
.component();
|
||||
sectionHeaderContainer.addItem(defaultSectionHeader, { flex: '0 0 auto' });
|
||||
this.defaultSectionComponents.push(defaultSectionHeader);
|
||||
// Delete - just used as a spacer
|
||||
const deleteSectionHeader = modelBuilder.text().component();
|
||||
sectionHeaderContainer.addItem(deleteSectionHeader, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
|
||||
// Table headers
|
||||
const headerRowContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
const ownersCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: nameColumnText }).component();
|
||||
headerRowContainer.addItem(ownersCell, { flex: '1 1 auto', CSSStyles: { 'width': `${permissionsNameColumnWidth}px`, 'min-width': `${permissionsNameColumnWidth}px`, ...cssStyles.tableHeaderCss } });
|
||||
if (includeSticky) {
|
||||
const stickyCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.stickyHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(stickyCell, { CSSStyles: { 'width': `${permissionsStickyColumnWidth}px`, 'min-width': `${permissionsStickyColumnWidth}px` } });
|
||||
rowsContainer.addItem(sectionHeaderContainer);
|
||||
|
||||
// Table headers
|
||||
const headerRowContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
|
||||
// Icon (spacer, no text)
|
||||
const typeIconCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ CSSStyles: { 'width': `${permissionsTypeIconColumnWidth}px`, 'min-width': `${permissionsTypeIconColumnWidth}px` } }).component();
|
||||
headerRowContainer.addItem(typeIconCell, { flex: '0 0 auto' });
|
||||
|
||||
// Name
|
||||
const nameCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: nameColumnText }).component();
|
||||
headerRowContainer.addItem(nameCell, { flex: '1 1 auto', CSSStyles: { 'width': `${permissionsNameColumnWidth}px`, 'min-width': `${permissionsNameColumnWidth}px`, ...cssStyles.tableHeaderCss } });
|
||||
if (includeSticky) {
|
||||
const stickyCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.stickyHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(stickyCell, { CSSStyles: { 'width': `${permissionsStickyColumnWidth}px`, 'min-width': `${permissionsStickyColumnWidth}px` } });
|
||||
}
|
||||
|
||||
// Access Permissions Group
|
||||
const accessReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const accessWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const accessExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px`, 'margin-right': '5px' } });
|
||||
// Default Permissions Group
|
||||
const defaultPermissionsHeadersContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
const defaultReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const defaultWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const defaultExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px` } });
|
||||
headerRowContainer.addItem(defaultPermissionsHeadersContainer, { flex: '0 0 auto' });
|
||||
this.defaultSectionComponents.push(defaultPermissionsHeadersContainer);
|
||||
|
||||
// Delete
|
||||
const deleteCell = modelBuilder.text().component();
|
||||
headerRowContainer.addItem(deleteCell, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
|
||||
rowsContainer.addItem(headerRowContainer);
|
||||
|
||||
return rowsContainer;
|
||||
}
|
||||
|
||||
// Access Permissions Group
|
||||
const accessReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const accessWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const accessExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px`, 'margin-right': '5px' } });
|
||||
// Default Permissions Group
|
||||
const defaultReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(defaultReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const defaultWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(defaultWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const defaultExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(defaultExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px` } });
|
||||
// Delete
|
||||
const deleteCell = modelBuilder.text().component();
|
||||
headerRowContainer.addItem(deleteCell, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
|
||||
rowsContainer.addItem(headerRowContainer);
|
||||
|
||||
return rowsContainer;
|
||||
}
|
||||
|
||||
function createCheckbox(builder: azdata.ModelBuilder, checked: boolean, containerWidth: number, containerHeight: number): { container: azdata.FlexContainer, checkbox: azdata.CheckBoxComponent } {
|
||||
@@ -388,7 +446,6 @@ function createCheckbox(builder: azdata.ModelBuilder, checked: boolean, containe
|
||||
.withProperties<azdata.CheckBoxProperties>({ checked: checked, height: 20, width: 20 }).component();
|
||||
const container = builder.flexContainer()
|
||||
.withLayout({ width: containerWidth, height: containerHeight })
|
||||
//.withItems([checkbox], { CSSStyles: { ...cssStyles.permissionCheckboxCss }})
|
||||
.component();
|
||||
container.addItem(checkbox, { CSSStyles: { ...cssStyles.permissionCheckboxCss } });
|
||||
return {
|
||||
|
||||
@@ -11,9 +11,10 @@ import * as through from 'through2';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as auth from '../util/auth';
|
||||
import { IHdfsOptions, IRequestParams } from '../objectExplorerNodeProvider/fileSources';
|
||||
import { IAclStatus, AclEntry, parseAcl, AclPermissionType, parseAclPermissionFromOctal, AclEntryScope } from './aclEntry';
|
||||
import { PermissionStatus, AclEntry, parseAcl, PermissionType, parseAclPermissionFromOctal, AclEntryScope } from './aclEntry';
|
||||
import { Mount } from './mount';
|
||||
import { everyoneName } from '../localizedConstants';
|
||||
import { FileStatus, parseHdfsFileType } from './fileStatus';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const ErrorMessageInvalidDataStructure = localize('webhdfs.invalidDataStructure', "Invalid Data Structure");
|
||||
@@ -75,7 +76,7 @@ export class WebHDFS {
|
||||
endpoint.pathname = this._opts.path + path;
|
||||
let searchOpts = Object.assign(
|
||||
{ 'op': operation },
|
||||
this._opts.user ? { 'user.name': this._opts.user } : {},
|
||||
// this._opts.user ? { 'user.name': this._opts.user } : {},
|
||||
params || {}
|
||||
);
|
||||
endpoint.search = querystring.stringify(searchOpts);
|
||||
@@ -420,13 +421,42 @@ export class WebHDFS {
|
||||
});
|
||||
}
|
||||
|
||||
public getFileStatus(path: string, callback: (error: HdfsError, fileStatus: FileStatus) => void): void {
|
||||
this.checkArgDefined('path', path);
|
||||
|
||||
let endpoint = this.getOperationEndpoint('getfilestatus', path);
|
||||
this.sendRequest('GET', endpoint, undefined, (error, response) => {
|
||||
if (!callback) { return; }
|
||||
if (error) {
|
||||
callback(error, undefined);
|
||||
} else if (response.body.hasOwnProperty('FileStatus')) {
|
||||
const fileStatus = new FileStatus(
|
||||
response.body.FileStatus.accessTime || '',
|
||||
response.body.FileStatus.blockSize || '',
|
||||
response.body.FileStatus.group || '',
|
||||
response.body.FileStatus.length || '',
|
||||
response.body.FileStatus.modificationTime || '',
|
||||
response.body.FileStatus.owner || '',
|
||||
response.body.FileStatus.pathSuffix || '',
|
||||
response.body.FileStatus.permission || '',
|
||||
response.body.FileStatus.replication || '',
|
||||
response.body.FileStatus.snapshotEnabled || '',
|
||||
parseHdfsFileType(response.body.FileStatus.type || 'undefined')
|
||||
);
|
||||
callback(undefined, fileStatus);
|
||||
} else {
|
||||
callback(new HdfsError(ErrorMessageInvalidDataStructure), undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ACL status for given path
|
||||
* @param path The path to the file/folder to get the status of
|
||||
* @param callback Callback to handle the response
|
||||
* @returns void
|
||||
*/
|
||||
public getAclStatus(path: string, callback: (error: HdfsError, aclStatus: IAclStatus) => void): void {
|
||||
public getAclStatus(path: string, callback: (error: HdfsError, permissionStatus: PermissionStatus) => void): void {
|
||||
this.checkArgDefined('path', path);
|
||||
|
||||
let endpoint = this.getOperationEndpoint('getaclstatus', path);
|
||||
@@ -436,14 +466,17 @@ export class WebHDFS {
|
||||
callback(error, undefined);
|
||||
} else if (response.body.hasOwnProperty('AclStatus')) {
|
||||
const permissions = parseAclPermissionFromOctal(response.body.AclStatus.permission);
|
||||
const aclStatus: IAclStatus = {
|
||||
owner: new AclEntry(AclEntryScope.access, AclPermissionType.owner, '', response.body.AclStatus.owner || '', permissions.owner),
|
||||
group: new AclEntry(AclEntryScope.access, AclPermissionType.group, '', response.body.AclStatus.group || '', permissions.group),
|
||||
other: new AclEntry(AclEntryScope.access, AclPermissionType.other, '', everyoneName, permissions.other),
|
||||
stickyBit: !!response.body.AclStatus.stickyBit,
|
||||
entries: (<any[]>response.body.AclStatus.entries).map(entry => parseAcl(entry)).reduce((acc, parsedEntries) => acc.concat(parsedEntries), [])
|
||||
};
|
||||
callback(undefined, aclStatus);
|
||||
const permissionStatus = new PermissionStatus(
|
||||
new AclEntry(AclEntryScope.access, PermissionType.owner, '', response.body.AclStatus.owner || '', permissions.owner),
|
||||
new AclEntry(AclEntryScope.access, PermissionType.group, '', response.body.AclStatus.group || '', permissions.group),
|
||||
new AclEntry(AclEntryScope.access, PermissionType.other, '', everyoneName, permissions.other),
|
||||
!!response.body.AclStatus.stickyBit,
|
||||
// We filter out empty names here since those are already added by the permission bits - WebHDFS creates an extra ACL
|
||||
// entry for the owning group whenever another ACL is added.
|
||||
(<any[]>response.body.AclStatus.entries).map(entry => parseAcl(entry))
|
||||
.reduce((acc, parsedEntries) => acc.concat(parsedEntries), [])
|
||||
.filter(e => e.name !== ''));
|
||||
callback(undefined, permissionStatus);
|
||||
} else {
|
||||
callback(new HdfsError(ErrorMessageInvalidDataStructure), undefined);
|
||||
}
|
||||
@@ -473,6 +506,20 @@ export class WebHDFS {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission octal (sticky, owner, group & other) for a file/folder
|
||||
* @param path The path to the file/folder to set the permission of
|
||||
* @param permissionStatus The status containing the permission to set
|
||||
*/
|
||||
public setPermission(path: string, permissionStatus: PermissionStatus, callback: (error: HdfsError) => void): void {
|
||||
this.checkArgDefined('path', path);
|
||||
this.checkArgDefined('permissionStatus', permissionStatus);
|
||||
let endpoint = this.getOperationEndpoint('setpermission', path, { permission: permissionStatus.permissionOctal });
|
||||
this.sendRequest('PUT', endpoint, undefined, (error) => {
|
||||
return callback && callback(error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all mounts for a HDFS connection
|
||||
* @param callback Callback to handle the response
|
||||
|
||||
@@ -14,6 +14,8 @@ export class IconPathHelper {
|
||||
private static extensionContext: vscode.ExtensionContext;
|
||||
|
||||
public static delete: IconPath;
|
||||
public static user: IconPath;
|
||||
public static group: IconPath;
|
||||
|
||||
public static setExtensionContext(extensionContext: vscode.ExtensionContext) {
|
||||
IconPathHelper.extensionContext = extensionContext;
|
||||
@@ -21,5 +23,13 @@ export class IconPathHelper {
|
||||
dark: IconPathHelper.extensionContext.asAbsolutePath('resources/dark/delete_inverse.svg'),
|
||||
light: IconPathHelper.extensionContext.asAbsolutePath('resources/light/delete.svg')
|
||||
};
|
||||
IconPathHelper.user = {
|
||||
dark: IconPathHelper.extensionContext.asAbsolutePath('resources/dark/user_inverse.svg'),
|
||||
light: IconPathHelper.extensionContext.asAbsolutePath('resources/light/user.svg')
|
||||
};
|
||||
IconPathHelper.group = {
|
||||
dark: IconPathHelper.extensionContext.asAbsolutePath('resources/dark/group_inverse.svg'),
|
||||
light: IconPathHelper.extensionContext.asAbsolutePath('resources/light/group.svg')
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ import * as nls from 'vscode-nls';
|
||||
|
||||
import * as constants from '../constants';
|
||||
import { WebHDFS, HdfsError } from '../hdfs/webhdfs';
|
||||
import { AclEntry, IAclStatus } from '../hdfs/aclEntry';
|
||||
import { AclEntry, PermissionStatus } from '../hdfs/aclEntry';
|
||||
import { Mount, MountStatus } from '../hdfs/mount';
|
||||
import { FileStatus } from '../hdfs/fileStatus';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -68,11 +69,15 @@ export interface IFileSource {
|
||||
readFileLines(path: string, maxLines: number): Promise<Buffer>;
|
||||
writeFile(localFile: IFile, remoteDir: string): Promise<string>;
|
||||
delete(path: string, recursive?: boolean): Promise<void>;
|
||||
/**
|
||||
* Retrieves the file status for the specified path (may be a file or directory)
|
||||
*/
|
||||
getFileStatus(path: string): Promise<FileStatus>;
|
||||
/**
|
||||
* Get ACL status for given path
|
||||
* @param path The path to the file/folder to get the status of
|
||||
*/
|
||||
getAclStatus(path: string): Promise<IAclStatus>;
|
||||
getAclStatus(path: string): Promise<PermissionStatus>;
|
||||
/**
|
||||
* Sets the ACL status for given path
|
||||
* @param path The path to the file/folder to set the ACL on
|
||||
@@ -82,6 +87,12 @@ export interface IFileSource {
|
||||
* @param aclEntries The ACL entries to set
|
||||
*/
|
||||
setAcl(path: string, ownerEntry: AclEntry, groupEntry: AclEntry, otherEntry: AclEntry, aclEntries: AclEntry[]): Promise<void>;
|
||||
/**
|
||||
* Sets the permission octal (sticky, owner, group & other) for a file/folder
|
||||
* @param path The path to the file/folder to set the permission of
|
||||
* @param aclStatus The status containing the permission to set
|
||||
*/
|
||||
setPermission(path: string, aclStatus: PermissionStatus): Promise<void>;
|
||||
exists(path: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -344,17 +355,29 @@ export class HdfsFileSource implements IFileSource {
|
||||
});
|
||||
}
|
||||
|
||||
public getFileStatus(path: string): Promise<FileStatus> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.getFileStatus(path, (error: HdfsError, fileStatus: FileStatus) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(fileStatus);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ACL status for given path
|
||||
* @param path The path to the file/folder to get the status of
|
||||
*/
|
||||
public getAclStatus(path: string): Promise<IAclStatus> {
|
||||
public getAclStatus(path: string): Promise<PermissionStatus> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.getAclStatus(path, (error: HdfsError, aclStatus: IAclStatus) => {
|
||||
this.client.getAclStatus(path, (error: HdfsError, permissionStatus: PermissionStatus) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(aclStatus);
|
||||
resolve(permissionStatus);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -379,4 +402,21 @@ export class HdfsFileSource implements IFileSource {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission octal (sticky, owner, group & other) for a file/folder
|
||||
* @param path The path to the file/folder to set the permission of
|
||||
* @param aclStatus The status containing the permission to set
|
||||
*/
|
||||
public setPermission(path: string, aclStatus: PermissionStatus): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.setPermission(path, aclStatus, (error: HdfsError) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
8
src/sql/azdata.d.ts
vendored
8
src/sql/azdata.d.ts
vendored
@@ -3109,12 +3109,10 @@ declare module 'azdata' {
|
||||
requiredIndicator?: boolean;
|
||||
}
|
||||
|
||||
export interface ImageComponentProperties {
|
||||
src: string;
|
||||
alt?: string;
|
||||
height?: number | string;
|
||||
width?: number | string;
|
||||
export interface ImageComponentProperties extends ComponentProperties, ComponentWithIcon {
|
||||
|
||||
}
|
||||
|
||||
export interface LinkArea {
|
||||
text: string;
|
||||
url: string;
|
||||
|
||||
9
src/sql/sqlops.proposed.d.ts
vendored
9
src/sql/sqlops.proposed.d.ts
vendored
@@ -26,6 +26,7 @@ declare module 'sqlops' {
|
||||
webView(): ComponentBuilder<WebViewComponent>;
|
||||
editor(): ComponentBuilder<EditorComponent>;
|
||||
text(): ComponentBuilder<TextComponent>;
|
||||
image(): ComponentBuilder<ImageComponent>;
|
||||
button(): ComponentBuilder<ButtonComponent>;
|
||||
dropDown(): ComponentBuilder<DropDownComponent>;
|
||||
tree<T>(): ComponentBuilder<TreeComponent<T>>;
|
||||
@@ -595,6 +596,10 @@ declare module 'sqlops' {
|
||||
links?: LinkArea[];
|
||||
}
|
||||
|
||||
export interface ImageComponentProperties extends ComponentProperties, ComponentWithIcon {
|
||||
|
||||
}
|
||||
|
||||
export interface LinkArea {
|
||||
text: string;
|
||||
url: string;
|
||||
@@ -731,6 +736,10 @@ declare module 'sqlops' {
|
||||
onDidClick: vscode.Event<any>;
|
||||
}
|
||||
|
||||
export interface ImageComponent extends Component, ImageComponentProperties {
|
||||
|
||||
}
|
||||
|
||||
export interface HyperlinkComponent extends Component, HyperlinkComponentProperties {
|
||||
}
|
||||
|
||||
|
||||
@@ -693,6 +693,34 @@ class ComponentWrapper implements azdata.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentWithIconWrapper extends ComponentWrapper {
|
||||
|
||||
constructor(proxy: MainThreadModelViewShape, handle: number, type: ModelComponentTypes, id: string) {
|
||||
super(proxy, handle, type, id);
|
||||
}
|
||||
|
||||
public get iconPath(): string | URI | { light: string | URI; dark: string | URI } {
|
||||
return this.properties['iconPath'];
|
||||
}
|
||||
public set iconPath(v: string | URI | { light: string | URI; dark: string | URI }) {
|
||||
this.setProperty('iconPath', v);
|
||||
}
|
||||
|
||||
public get iconHeight(): string | number {
|
||||
return this.properties['iconHeight'];
|
||||
}
|
||||
public set iconHeight(v: string | number) {
|
||||
this.setProperty('iconHeight', v);
|
||||
}
|
||||
|
||||
public get iconWidth(): string | number {
|
||||
return this.properties['iconWidth'];
|
||||
}
|
||||
public set iconWidth(v: string | number) {
|
||||
this.setProperty('iconWidth', v);
|
||||
}
|
||||
}
|
||||
|
||||
class ContainerWrapper<T, U> extends ComponentWrapper implements azdata.Container<T, U> {
|
||||
|
||||
constructor(proxy: MainThreadModelViewShape, handle: number, type: ModelComponentTypes, id: string) {
|
||||
@@ -1152,40 +1180,12 @@ class TextComponentWrapper extends ComponentWrapper implements azdata.TextCompon
|
||||
}
|
||||
}
|
||||
|
||||
class ImageComponentWrapper extends ComponentWrapper implements azdata.ImageComponentProperties {
|
||||
class ImageComponentWrapper extends ComponentWithIconWrapper implements azdata.ImageComponentProperties {
|
||||
|
||||
constructor(proxy: MainThreadModelViewShape, handle: number, id: string) {
|
||||
super(proxy, handle, ModelComponentTypes.Image, id);
|
||||
this.properties = {};
|
||||
}
|
||||
|
||||
public get src(): string {
|
||||
return this.properties['src'];
|
||||
}
|
||||
public set src(v: string) {
|
||||
this.setProperty('src', v);
|
||||
}
|
||||
|
||||
public get alt(): string {
|
||||
return this.properties['alt'];
|
||||
}
|
||||
public set alt(v: string) {
|
||||
this.setProperty('alt', v);
|
||||
}
|
||||
|
||||
public get height(): number | string {
|
||||
return this.properties['height'];
|
||||
}
|
||||
public set height(v: number | string) {
|
||||
this.setProperty('height', v);
|
||||
}
|
||||
|
||||
public get width(): number | string {
|
||||
return this.properties['width'];
|
||||
}
|
||||
public set width(v: number | string) {
|
||||
this.setProperty('width', v);
|
||||
}
|
||||
}
|
||||
|
||||
class TableComponentWrapper extends ComponentWrapper implements azdata.TableComponent {
|
||||
@@ -1391,7 +1391,7 @@ class ListBoxWrapper extends ComponentWrapper implements azdata.ListBoxComponent
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonWrapper extends ComponentWrapper implements azdata.ButtonComponent {
|
||||
class ButtonWrapper extends ComponentWithIconWrapper implements azdata.ButtonComponent {
|
||||
|
||||
constructor(proxy: MainThreadModelViewShape, handle: number, id: string) {
|
||||
super(proxy, handle, ModelComponentTypes.Button, id);
|
||||
@@ -1406,27 +1406,6 @@ class ButtonWrapper extends ComponentWrapper implements azdata.ButtonComponent {
|
||||
this.setProperty('label', v);
|
||||
}
|
||||
|
||||
public get iconPath(): string | URI | { light: string | URI; dark: string | URI } {
|
||||
return this.properties['iconPath'];
|
||||
}
|
||||
public set iconPath(v: string | URI | { light: string | URI; dark: string | URI }) {
|
||||
this.setProperty('iconPath', v);
|
||||
}
|
||||
|
||||
public get iconHeight(): string | number {
|
||||
return this.properties['iconHeight'];
|
||||
}
|
||||
public set iconHeight(v: string | number) {
|
||||
this.setProperty('iconHeight', v);
|
||||
}
|
||||
|
||||
public get iconWidth(): string | number {
|
||||
return this.properties['iconWidth'];
|
||||
}
|
||||
public set iconWidth(v: string | number) {
|
||||
this.setProperty('iconWidth', v);
|
||||
}
|
||||
|
||||
public get title(): string {
|
||||
return this.properties['title'];
|
||||
}
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/image';
|
||||
import {
|
||||
Component, Input, Inject, ChangeDetectorRef, forwardRef,
|
||||
OnDestroy, AfterViewInit, ElementRef
|
||||
OnDestroy, AfterViewInit, ElementRef, ViewChild
|
||||
} from '@angular/core';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IComponent, IComponentDescriptor, IModelStore } from 'sql/workbench/browser/modelComponents/interfaces';
|
||||
import { ComponentWithIconBase } from 'sql/workbench/browser/modelComponents/componentWithIconBase';
|
||||
|
||||
@Component({
|
||||
selector: 'modelview-image',
|
||||
template: `
|
||||
<img [style.width]="getWidth()" [style.height]="getHeight()" [src]="src" [alt]="alt">`
|
||||
<div #imageContainer [style.title]="title" [style.width]="getWidth()" [style.height]="getHeight()" [style.background-size]="getImageSize()">`
|
||||
})
|
||||
export default class ImageComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
||||
export default class ImageComponent extends ComponentWithIconBase implements IComponent, OnDestroy, AfterViewInit {
|
||||
@Input() descriptor: IComponentDescriptor;
|
||||
@Input() modelStore: IModelStore;
|
||||
@ViewChild('imageContainer', { read: ElementRef }) imageContainer: ElementRef;
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||
@@ -45,19 +45,27 @@ export default class ImageComponent extends ComponentBase implements IComponent,
|
||||
this.layout();
|
||||
}
|
||||
|
||||
public set src(newValue: string) {
|
||||
this.setPropertyFromUI<azdata.ImageComponentProperties, string>((properties, value) => { properties.src = value; }, newValue);
|
||||
public setProperties(properties: { [key: string]: any; }): void {
|
||||
super.setProperties(properties);
|
||||
this.updateIcon();
|
||||
this._changeRef.detectChanges();
|
||||
}
|
||||
|
||||
public get src(): string {
|
||||
return this.getPropertyOrDefault<azdata.ImageComponentProperties, string>((props) => props.src, '');
|
||||
protected updateIcon() {
|
||||
if (this.iconPath) {
|
||||
if (!this._iconClass) {
|
||||
super.updateIcon();
|
||||
DOM.addClasses(this.imageContainer.nativeElement, this._iconClass, 'icon');
|
||||
} else {
|
||||
super.updateIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public set alt(newValue: string) {
|
||||
this.setPropertyFromUI<azdata.ImageComponentProperties, string>((properties, value) => { properties.alt = value; }, newValue);
|
||||
}
|
||||
|
||||
public get alt(): string {
|
||||
return this.getPropertyOrDefault<azdata.ImageComponentProperties, string>((props) => props.alt, '');
|
||||
/**
|
||||
* Helper to get the size string for the background-size CSS property
|
||||
*/
|
||||
private getImageSize(): string {
|
||||
return `${this.getIconWidth()} ${this.getIconHeight()}`;
|
||||
}
|
||||
}
|
||||
|
||||
10
src/sql/workbench/browser/modelComponents/media/image.css
Normal file
10
src/sql/workbench/browser/modelComponents/media/image.css
Normal file
@@ -0,0 +1,10 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
modelview-image div.icon {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
}
|
||||
Reference in New Issue
Block a user