organizations.rs 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893
  1. use num_traits::FromPrimitive;
  2. use rocket::serde::json::Json;
  3. use rocket::Route;
  4. use serde_json::Value;
  5. use crate::{
  6. api::{
  7. core::{log_event, CipherSyncData, CipherSyncType},
  8. ApiResult, EmptyResult, JsonResult, JsonUpcase, JsonUpcaseVec, JsonVec, Notify, NumberOrString, PasswordData,
  9. UpdateType,
  10. },
  11. auth::{decode_invite, AdminHeaders, Headers, ManagerHeaders, ManagerHeadersLoose, OwnerHeaders},
  12. db::{models::*, DbConn},
  13. error::Error,
  14. mail,
  15. util::convert_json_key_lcase_first,
  16. CONFIG,
  17. };
  18. pub fn routes() -> Vec<Route> {
  19. routes![
  20. get_organization,
  21. create_organization,
  22. delete_organization,
  23. post_delete_organization,
  24. leave_organization,
  25. get_user_collections,
  26. get_org_collections,
  27. get_org_collections_details,
  28. get_org_collection_detail,
  29. get_collection_users,
  30. put_collection_users,
  31. put_organization,
  32. post_organization,
  33. post_organization_collections,
  34. delete_organization_collection_user,
  35. post_organization_collection_delete_user,
  36. post_organization_collection_update,
  37. put_organization_collection_update,
  38. delete_organization_collection,
  39. post_organization_collection_delete,
  40. bulk_delete_organization_collections,
  41. get_org_details,
  42. get_org_users,
  43. send_invite,
  44. reinvite_user,
  45. bulk_reinvite_user,
  46. confirm_invite,
  47. bulk_confirm_invite,
  48. accept_invite,
  49. get_user,
  50. edit_user,
  51. put_organization_user,
  52. delete_user,
  53. bulk_delete_user,
  54. post_delete_user,
  55. post_org_import,
  56. list_policies,
  57. list_policies_token,
  58. get_policy,
  59. put_policy,
  60. get_organization_tax,
  61. get_plans,
  62. get_plans_tax_rates,
  63. import,
  64. post_org_keys,
  65. get_organization_keys,
  66. bulk_public_keys,
  67. deactivate_organization_user,
  68. bulk_deactivate_organization_user,
  69. revoke_organization_user,
  70. bulk_revoke_organization_user,
  71. activate_organization_user,
  72. bulk_activate_organization_user,
  73. restore_organization_user,
  74. bulk_restore_organization_user,
  75. get_groups,
  76. post_groups,
  77. get_group,
  78. put_group,
  79. post_group,
  80. get_group_details,
  81. delete_group,
  82. post_delete_group,
  83. bulk_delete_groups,
  84. get_group_users,
  85. put_group_users,
  86. get_user_groups,
  87. post_user_groups,
  88. put_user_groups,
  89. delete_group_user,
  90. post_delete_group_user,
  91. put_reset_password_enrollment,
  92. get_reset_password_details,
  93. put_reset_password,
  94. get_org_export
  95. ]
  96. }
  97. #[derive(Deserialize)]
  98. #[allow(non_snake_case)]
  99. struct OrgData {
  100. BillingEmail: String,
  101. CollectionName: String,
  102. Key: String,
  103. Name: String,
  104. Keys: Option<OrgKeyData>,
  105. #[serde(rename = "PlanType")]
  106. _PlanType: NumberOrString, // Ignored, always use the same plan
  107. }
  108. #[derive(Deserialize, Debug)]
  109. #[allow(non_snake_case)]
  110. struct OrganizationUpdateData {
  111. BillingEmail: String,
  112. Name: String,
  113. }
  114. #[derive(Deserialize)]
  115. #[allow(non_snake_case)]
  116. struct NewCollectionData {
  117. Name: String,
  118. Groups: Vec<NewCollectionObjectData>,
  119. Users: Vec<NewCollectionObjectData>,
  120. }
  121. #[derive(Deserialize)]
  122. #[allow(non_snake_case)]
  123. struct NewCollectionObjectData {
  124. HidePasswords: bool,
  125. Id: String,
  126. ReadOnly: bool,
  127. }
  128. #[derive(Deserialize)]
  129. #[allow(non_snake_case)]
  130. struct OrgKeyData {
  131. EncryptedPrivateKey: String,
  132. PublicKey: String,
  133. }
  134. #[derive(Deserialize, Debug)]
  135. #[allow(non_snake_case)]
  136. struct OrgBulkIds {
  137. Ids: Vec<String>,
  138. }
  139. #[post("/organizations", data = "<data>")]
  140. async fn create_organization(headers: Headers, data: JsonUpcase<OrgData>, mut conn: DbConn) -> JsonResult {
  141. if !CONFIG.is_org_creation_allowed(&headers.user.email) {
  142. err!("User not allowed to create organizations")
  143. }
  144. if OrgPolicy::is_applicable_to_user(&headers.user.uuid, OrgPolicyType::SingleOrg, None, &mut conn).await {
  145. err!(
  146. "You may not create an organization. You belong to an organization which has a policy that prohibits you from being a member of any other organization."
  147. )
  148. }
  149. let data: OrgData = data.into_inner().data;
  150. let (private_key, public_key) = if data.Keys.is_some() {
  151. let keys: OrgKeyData = data.Keys.unwrap();
  152. (Some(keys.EncryptedPrivateKey), Some(keys.PublicKey))
  153. } else {
  154. (None, None)
  155. };
  156. let org = Organization::new(data.Name, data.BillingEmail, private_key, public_key);
  157. let mut user_org = UserOrganization::new(headers.user.uuid, org.uuid.clone());
  158. let collection = Collection::new(org.uuid.clone(), data.CollectionName);
  159. user_org.akey = data.Key;
  160. user_org.access_all = true;
  161. user_org.atype = UserOrgType::Owner as i32;
  162. user_org.status = UserOrgStatus::Confirmed as i32;
  163. org.save(&mut conn).await?;
  164. user_org.save(&mut conn).await?;
  165. collection.save(&mut conn).await?;
  166. Ok(Json(org.to_json()))
  167. }
  168. #[delete("/organizations/<org_id>", data = "<data>")]
  169. async fn delete_organization(
  170. org_id: &str,
  171. data: JsonUpcase<PasswordData>,
  172. headers: OwnerHeaders,
  173. mut conn: DbConn,
  174. ) -> EmptyResult {
  175. let data: PasswordData = data.into_inner().data;
  176. let password_hash = data.MasterPasswordHash;
  177. if !headers.user.check_valid_password(&password_hash) {
  178. err!("Invalid password")
  179. }
  180. match Organization::find_by_uuid(org_id, &mut conn).await {
  181. None => err!("Organization not found"),
  182. Some(org) => org.delete(&mut conn).await,
  183. }
  184. }
  185. #[post("/organizations/<org_id>/delete", data = "<data>")]
  186. async fn post_delete_organization(
  187. org_id: &str,
  188. data: JsonUpcase<PasswordData>,
  189. headers: OwnerHeaders,
  190. conn: DbConn,
  191. ) -> EmptyResult {
  192. delete_organization(org_id, data, headers, conn).await
  193. }
  194. #[post("/organizations/<org_id>/leave")]
  195. async fn leave_organization(org_id: &str, headers: Headers, mut conn: DbConn) -> EmptyResult {
  196. match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
  197. None => err!("User not part of organization"),
  198. Some(user_org) => {
  199. if user_org.atype == UserOrgType::Owner
  200. && UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, &mut conn).await <= 1
  201. {
  202. err!("The last owner can't leave")
  203. }
  204. log_event(
  205. EventType::OrganizationUserRemoved as i32,
  206. &user_org.uuid,
  207. org_id,
  208. headers.user.uuid.clone(),
  209. headers.device.atype,
  210. &headers.ip.ip,
  211. &mut conn,
  212. )
  213. .await;
  214. user_org.delete(&mut conn).await
  215. }
  216. }
  217. }
  218. #[get("/organizations/<org_id>")]
  219. async fn get_organization(org_id: &str, _headers: OwnerHeaders, mut conn: DbConn) -> JsonResult {
  220. match Organization::find_by_uuid(org_id, &mut conn).await {
  221. Some(organization) => Ok(Json(organization.to_json())),
  222. None => err!("Can't find organization details"),
  223. }
  224. }
  225. #[put("/organizations/<org_id>", data = "<data>")]
  226. async fn put_organization(
  227. org_id: &str,
  228. headers: OwnerHeaders,
  229. data: JsonUpcase<OrganizationUpdateData>,
  230. conn: DbConn,
  231. ) -> JsonResult {
  232. post_organization(org_id, headers, data, conn).await
  233. }
  234. #[post("/organizations/<org_id>", data = "<data>")]
  235. async fn post_organization(
  236. org_id: &str,
  237. headers: OwnerHeaders,
  238. data: JsonUpcase<OrganizationUpdateData>,
  239. mut conn: DbConn,
  240. ) -> JsonResult {
  241. let data: OrganizationUpdateData = data.into_inner().data;
  242. let mut org = match Organization::find_by_uuid(org_id, &mut conn).await {
  243. Some(organization) => organization,
  244. None => err!("Can't find organization details"),
  245. };
  246. org.name = data.Name;
  247. org.billing_email = data.BillingEmail;
  248. org.save(&mut conn).await?;
  249. log_event(
  250. EventType::OrganizationUpdated as i32,
  251. org_id,
  252. org_id,
  253. headers.user.uuid.clone(),
  254. headers.device.atype,
  255. &headers.ip.ip,
  256. &mut conn,
  257. )
  258. .await;
  259. Ok(Json(org.to_json()))
  260. }
  261. // GET /api/collections?writeOnly=false
  262. #[get("/collections")]
  263. async fn get_user_collections(headers: Headers, mut conn: DbConn) -> Json<Value> {
  264. Json(json!({
  265. "Data":
  266. Collection::find_by_user_uuid(headers.user.uuid.clone(), &mut conn).await
  267. .iter()
  268. .map(Collection::to_json)
  269. .collect::<Value>(),
  270. "Object": "list",
  271. "ContinuationToken": null,
  272. }))
  273. }
  274. #[get("/organizations/<org_id>/collections")]
  275. async fn get_org_collections(org_id: &str, _headers: ManagerHeadersLoose, mut conn: DbConn) -> Json<Value> {
  276. Json(json!({
  277. "Data": _get_org_collections(org_id, &mut conn).await,
  278. "Object": "list",
  279. "ContinuationToken": null,
  280. }))
  281. }
  282. #[get("/organizations/<org_id>/collections/details")]
  283. async fn get_org_collections_details(org_id: &str, headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult {
  284. let mut data = Vec::new();
  285. let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
  286. Some(u) => u,
  287. None => err!("User is not part of organization"),
  288. };
  289. let coll_users = CollectionUser::find_by_organization(org_id, &mut conn).await;
  290. for col in Collection::find_by_organization(org_id, &mut conn).await {
  291. let groups: Vec<Value> = if CONFIG.org_groups_enabled() {
  292. CollectionGroup::find_by_collection(&col.uuid, &mut conn)
  293. .await
  294. .iter()
  295. .map(|collection_group| {
  296. SelectionReadOnly::to_collection_group_details_read_only(collection_group).to_json()
  297. })
  298. .collect()
  299. } else {
  300. // The Bitwarden clients seem to call this API regardless of whether groups are enabled,
  301. // so just act as if there are no groups.
  302. Vec::with_capacity(0)
  303. };
  304. let mut assigned = false;
  305. let users: Vec<Value> = coll_users
  306. .iter()
  307. .filter(|collection_user| collection_user.collection_uuid == col.uuid)
  308. .map(|collection_user| {
  309. // Remember `user_uuid` is swapped here with the `user_org.uuid` with a join during the `CollectionUser::find_by_organization` call.
  310. // We check here if the current user is assigned to this collection or not.
  311. if collection_user.user_uuid == user_org.uuid {
  312. assigned = true;
  313. }
  314. SelectionReadOnly::to_collection_user_details_read_only(collection_user).to_json()
  315. })
  316. .collect();
  317. if user_org.access_all {
  318. assigned = true;
  319. }
  320. let mut json_object = col.to_json();
  321. json_object["Assigned"] = json!(assigned);
  322. json_object["Users"] = json!(users);
  323. json_object["Groups"] = json!(groups);
  324. json_object["Object"] = json!("collectionAccessDetails");
  325. data.push(json_object)
  326. }
  327. Ok(Json(json!({
  328. "Data": data,
  329. "Object": "list",
  330. "ContinuationToken": null,
  331. })))
  332. }
  333. async fn _get_org_collections(org_id: &str, conn: &mut DbConn) -> Value {
  334. Collection::find_by_organization(org_id, conn).await.iter().map(Collection::to_json).collect::<Value>()
  335. }
  336. #[post("/organizations/<org_id>/collections", data = "<data>")]
  337. async fn post_organization_collections(
  338. org_id: &str,
  339. headers: ManagerHeadersLoose,
  340. data: JsonUpcase<NewCollectionData>,
  341. mut conn: DbConn,
  342. ) -> JsonResult {
  343. let data: NewCollectionData = data.into_inner().data;
  344. let org = match Organization::find_by_uuid(org_id, &mut conn).await {
  345. Some(organization) => organization,
  346. None => err!("Can't find organization details"),
  347. };
  348. let collection = Collection::new(org.uuid, data.Name);
  349. collection.save(&mut conn).await?;
  350. log_event(
  351. EventType::CollectionCreated as i32,
  352. &collection.uuid,
  353. org_id,
  354. headers.user.uuid.clone(),
  355. headers.device.atype,
  356. &headers.ip.ip,
  357. &mut conn,
  358. )
  359. .await;
  360. for group in data.Groups {
  361. CollectionGroup::new(collection.uuid.clone(), group.Id, group.ReadOnly, group.HidePasswords)
  362. .save(&mut conn)
  363. .await?;
  364. }
  365. for user in data.Users {
  366. let org_user = match UserOrganization::find_by_uuid(&user.Id, &mut conn).await {
  367. Some(u) => u,
  368. None => err!("User is not part of organization"),
  369. };
  370. if org_user.access_all {
  371. continue;
  372. }
  373. CollectionUser::save(&org_user.user_uuid, &collection.uuid, user.ReadOnly, user.HidePasswords, &mut conn)
  374. .await?;
  375. }
  376. Ok(Json(collection.to_json()))
  377. }
  378. #[put("/organizations/<org_id>/collections/<col_id>", data = "<data>")]
  379. async fn put_organization_collection_update(
  380. org_id: &str,
  381. col_id: &str,
  382. headers: ManagerHeaders,
  383. data: JsonUpcase<NewCollectionData>,
  384. conn: DbConn,
  385. ) -> JsonResult {
  386. post_organization_collection_update(org_id, col_id, headers, data, conn).await
  387. }
  388. #[post("/organizations/<org_id>/collections/<col_id>", data = "<data>")]
  389. async fn post_organization_collection_update(
  390. org_id: &str,
  391. col_id: &str,
  392. headers: ManagerHeaders,
  393. data: JsonUpcase<NewCollectionData>,
  394. mut conn: DbConn,
  395. ) -> JsonResult {
  396. let data: NewCollectionData = data.into_inner().data;
  397. let org = match Organization::find_by_uuid(org_id, &mut conn).await {
  398. Some(organization) => organization,
  399. None => err!("Can't find organization details"),
  400. };
  401. let mut collection = match Collection::find_by_uuid(col_id, &mut conn).await {
  402. Some(collection) => collection,
  403. None => err!("Collection not found"),
  404. };
  405. if collection.org_uuid != org.uuid {
  406. err!("Collection is not owned by organization");
  407. }
  408. collection.name = data.Name;
  409. collection.save(&mut conn).await?;
  410. log_event(
  411. EventType::CollectionUpdated as i32,
  412. &collection.uuid,
  413. org_id,
  414. headers.user.uuid.clone(),
  415. headers.device.atype,
  416. &headers.ip.ip,
  417. &mut conn,
  418. )
  419. .await;
  420. CollectionGroup::delete_all_by_collection(col_id, &mut conn).await?;
  421. for group in data.Groups {
  422. CollectionGroup::new(String::from(col_id), group.Id, group.ReadOnly, group.HidePasswords)
  423. .save(&mut conn)
  424. .await?;
  425. }
  426. CollectionUser::delete_all_by_collection(col_id, &mut conn).await?;
  427. for user in data.Users {
  428. let org_user = match UserOrganization::find_by_uuid(&user.Id, &mut conn).await {
  429. Some(u) => u,
  430. None => err!("User is not part of organization"),
  431. };
  432. if org_user.access_all {
  433. continue;
  434. }
  435. CollectionUser::save(&org_user.user_uuid, col_id, user.ReadOnly, user.HidePasswords, &mut conn).await?;
  436. }
  437. Ok(Json(collection.to_json()))
  438. }
  439. #[delete("/organizations/<org_id>/collections/<col_id>/user/<org_user_id>")]
  440. async fn delete_organization_collection_user(
  441. org_id: &str,
  442. col_id: &str,
  443. org_user_id: &str,
  444. _headers: AdminHeaders,
  445. mut conn: DbConn,
  446. ) -> EmptyResult {
  447. let collection = match Collection::find_by_uuid(col_id, &mut conn).await {
  448. None => err!("Collection not found"),
  449. Some(collection) => {
  450. if collection.org_uuid == org_id {
  451. collection
  452. } else {
  453. err!("Collection and Organization id do not match")
  454. }
  455. }
  456. };
  457. match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
  458. None => err!("User not found in organization"),
  459. Some(user_org) => {
  460. match CollectionUser::find_by_collection_and_user(&collection.uuid, &user_org.user_uuid, &mut conn).await {
  461. None => err!("User not assigned to collection"),
  462. Some(col_user) => col_user.delete(&mut conn).await,
  463. }
  464. }
  465. }
  466. }
  467. #[post("/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id>")]
  468. async fn post_organization_collection_delete_user(
  469. org_id: &str,
  470. col_id: &str,
  471. org_user_id: &str,
  472. headers: AdminHeaders,
  473. conn: DbConn,
  474. ) -> EmptyResult {
  475. delete_organization_collection_user(org_id, col_id, org_user_id, headers, conn).await
  476. }
  477. async fn _delete_organization_collection(
  478. org_id: &str,
  479. col_id: &str,
  480. headers: &ManagerHeaders,
  481. conn: &mut DbConn,
  482. ) -> EmptyResult {
  483. match Collection::find_by_uuid(col_id, conn).await {
  484. None => err!("Collection not found"),
  485. Some(collection) => {
  486. if collection.org_uuid == org_id {
  487. log_event(
  488. EventType::CollectionDeleted as i32,
  489. &collection.uuid,
  490. org_id,
  491. headers.user.uuid.clone(),
  492. headers.device.atype,
  493. &headers.ip.ip,
  494. conn,
  495. )
  496. .await;
  497. collection.delete(conn).await
  498. } else {
  499. err!("Collection and Organization id do not match")
  500. }
  501. }
  502. }
  503. }
  504. #[delete("/organizations/<org_id>/collections/<col_id>")]
  505. async fn delete_organization_collection(
  506. org_id: &str,
  507. col_id: &str,
  508. headers: ManagerHeaders,
  509. mut conn: DbConn,
  510. ) -> EmptyResult {
  511. _delete_organization_collection(org_id, col_id, &headers, &mut conn).await
  512. }
  513. #[derive(Deserialize, Debug)]
  514. #[allow(non_snake_case, dead_code)]
  515. struct DeleteCollectionData {
  516. Id: String,
  517. OrgId: String,
  518. }
  519. #[post("/organizations/<org_id>/collections/<col_id>/delete", data = "<_data>")]
  520. async fn post_organization_collection_delete(
  521. org_id: &str,
  522. col_id: &str,
  523. headers: ManagerHeaders,
  524. _data: JsonUpcase<DeleteCollectionData>,
  525. mut conn: DbConn,
  526. ) -> EmptyResult {
  527. _delete_organization_collection(org_id, col_id, &headers, &mut conn).await
  528. }
  529. #[derive(Deserialize, Debug)]
  530. #[allow(non_snake_case)]
  531. struct BulkCollectionIds {
  532. Ids: Vec<String>,
  533. OrganizationId: String,
  534. }
  535. #[delete("/organizations/<org_id>/collections", data = "<data>")]
  536. async fn bulk_delete_organization_collections(
  537. org_id: &str,
  538. headers: ManagerHeadersLoose,
  539. data: JsonUpcase<BulkCollectionIds>,
  540. mut conn: DbConn,
  541. ) -> EmptyResult {
  542. let data: BulkCollectionIds = data.into_inner().data;
  543. if org_id != data.OrganizationId {
  544. err!("OrganizationId mismatch");
  545. }
  546. let collections = data.Ids;
  547. let headers = ManagerHeaders::from_loose(headers, &collections, &mut conn).await?;
  548. for col_id in collections {
  549. _delete_organization_collection(org_id, &col_id, &headers, &mut conn).await?
  550. }
  551. Ok(())
  552. }
  553. #[get("/organizations/<org_id>/collections/<coll_id>/details")]
  554. async fn get_org_collection_detail(
  555. org_id: &str,
  556. coll_id: &str,
  557. headers: ManagerHeaders,
  558. mut conn: DbConn,
  559. ) -> JsonResult {
  560. match Collection::find_by_uuid_and_user(coll_id, headers.user.uuid.clone(), &mut conn).await {
  561. None => err!("Collection not found"),
  562. Some(collection) => {
  563. if collection.org_uuid != org_id {
  564. err!("Collection is not owned by organization")
  565. }
  566. let user_org = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
  567. Some(u) => u,
  568. None => err!("User is not part of organization"),
  569. };
  570. let groups: Vec<Value> = if CONFIG.org_groups_enabled() {
  571. CollectionGroup::find_by_collection(&collection.uuid, &mut conn)
  572. .await
  573. .iter()
  574. .map(|collection_group| {
  575. SelectionReadOnly::to_collection_group_details_read_only(collection_group).to_json()
  576. })
  577. .collect()
  578. } else {
  579. // The Bitwarden clients seem to call this API regardless of whether groups are enabled,
  580. // so just act as if there are no groups.
  581. Vec::with_capacity(0)
  582. };
  583. let mut assigned = false;
  584. let users: Vec<Value> =
  585. CollectionUser::find_by_collection_swap_user_uuid_with_org_user_uuid(&collection.uuid, &mut conn)
  586. .await
  587. .iter()
  588. .map(|collection_user| {
  589. // Remember `user_uuid` is swapped here with the `user_org.uuid` with a join during the `find_by_collection_swap_user_uuid_with_org_user_uuid` call.
  590. // We check here if the current user is assigned to this collection or not.
  591. if collection_user.user_uuid == user_org.uuid {
  592. assigned = true;
  593. }
  594. SelectionReadOnly::to_collection_user_details_read_only(collection_user).to_json()
  595. })
  596. .collect();
  597. if user_org.access_all {
  598. assigned = true;
  599. }
  600. let mut json_object = collection.to_json();
  601. json_object["Assigned"] = json!(assigned);
  602. json_object["Users"] = json!(users);
  603. json_object["Groups"] = json!(groups);
  604. json_object["Object"] = json!("collectionAccessDetails");
  605. Ok(Json(json_object))
  606. }
  607. }
  608. }
  609. #[get("/organizations/<org_id>/collections/<coll_id>/users")]
  610. async fn get_collection_users(org_id: &str, coll_id: &str, _headers: ManagerHeaders, mut conn: DbConn) -> JsonResult {
  611. // Get org and collection, check that collection is from org
  612. let collection = match Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await {
  613. None => err!("Collection not found in Organization"),
  614. Some(collection) => collection,
  615. };
  616. let mut user_list = Vec::new();
  617. for col_user in CollectionUser::find_by_collection(&collection.uuid, &mut conn).await {
  618. user_list.push(
  619. UserOrganization::find_by_user_and_org(&col_user.user_uuid, org_id, &mut conn)
  620. .await
  621. .unwrap()
  622. .to_json_user_access_restrictions(&col_user),
  623. );
  624. }
  625. Ok(Json(json!(user_list)))
  626. }
  627. #[put("/organizations/<org_id>/collections/<coll_id>/users", data = "<data>")]
  628. async fn put_collection_users(
  629. org_id: &str,
  630. coll_id: &str,
  631. data: JsonUpcaseVec<CollectionData>,
  632. _headers: ManagerHeaders,
  633. mut conn: DbConn,
  634. ) -> EmptyResult {
  635. // Get org and collection, check that collection is from org
  636. if Collection::find_by_uuid_and_org(coll_id, org_id, &mut conn).await.is_none() {
  637. err!("Collection not found in Organization")
  638. }
  639. // Delete all the user-collections
  640. CollectionUser::delete_all_by_collection(coll_id, &mut conn).await?;
  641. // And then add all the received ones (except if the user has access_all)
  642. for d in data.iter().map(|d| &d.data) {
  643. let user = match UserOrganization::find_by_uuid(&d.Id, &mut conn).await {
  644. Some(u) => u,
  645. None => err!("User is not part of organization"),
  646. };
  647. if user.access_all {
  648. continue;
  649. }
  650. CollectionUser::save(&user.user_uuid, coll_id, d.ReadOnly, d.HidePasswords, &mut conn).await?;
  651. }
  652. Ok(())
  653. }
  654. #[derive(FromForm)]
  655. struct OrgIdData {
  656. #[field(name = "organizationId")]
  657. organization_id: String,
  658. }
  659. #[get("/ciphers/organization-details?<data..>")]
  660. async fn get_org_details(data: OrgIdData, headers: Headers, mut conn: DbConn) -> Json<Value> {
  661. Json(json!({
  662. "Data": _get_org_details(&data.organization_id, &headers.host, &headers.user.uuid, &mut conn).await,
  663. "Object": "list",
  664. "ContinuationToken": null,
  665. }))
  666. }
  667. async fn _get_org_details(org_id: &str, host: &str, user_uuid: &str, conn: &mut DbConn) -> Value {
  668. let ciphers = Cipher::find_by_org(org_id, conn).await;
  669. let cipher_sync_data = CipherSyncData::new(user_uuid, CipherSyncType::Organization, conn).await;
  670. let mut ciphers_json = Vec::with_capacity(ciphers.len());
  671. for c in ciphers {
  672. ciphers_json
  673. .push(c.to_json(host, user_uuid, Some(&cipher_sync_data), CipherSyncType::Organization, conn).await);
  674. }
  675. json!(ciphers_json)
  676. }
  677. #[derive(FromForm)]
  678. struct GetOrgUserData {
  679. #[field(name = "includeCollections")]
  680. include_collections: Option<bool>,
  681. #[field(name = "includeGroups")]
  682. include_groups: Option<bool>,
  683. }
  684. #[get("/organizations/<org_id>/users?<data..>")]
  685. async fn get_org_users(
  686. data: GetOrgUserData,
  687. org_id: &str,
  688. _headers: ManagerHeadersLoose,
  689. mut conn: DbConn,
  690. ) -> Json<Value> {
  691. let mut users_json = Vec::new();
  692. for u in UserOrganization::find_by_org(org_id, &mut conn).await {
  693. users_json.push(
  694. u.to_json_user_details(
  695. data.include_collections.unwrap_or(false),
  696. data.include_groups.unwrap_or(false),
  697. &mut conn,
  698. )
  699. .await,
  700. );
  701. }
  702. Json(json!({
  703. "Data": users_json,
  704. "Object": "list",
  705. "ContinuationToken": null,
  706. }))
  707. }
  708. #[post("/organizations/<org_id>/keys", data = "<data>")]
  709. async fn post_org_keys(
  710. org_id: &str,
  711. data: JsonUpcase<OrgKeyData>,
  712. _headers: AdminHeaders,
  713. mut conn: DbConn,
  714. ) -> JsonResult {
  715. let data: OrgKeyData = data.into_inner().data;
  716. let mut org = match Organization::find_by_uuid(org_id, &mut conn).await {
  717. Some(organization) => {
  718. if organization.private_key.is_some() && organization.public_key.is_some() {
  719. err!("Organization Keys already exist")
  720. }
  721. organization
  722. }
  723. None => err!("Can't find organization details"),
  724. };
  725. org.private_key = Some(data.EncryptedPrivateKey);
  726. org.public_key = Some(data.PublicKey);
  727. org.save(&mut conn).await?;
  728. Ok(Json(json!({
  729. "Object": "organizationKeys",
  730. "PublicKey": org.public_key,
  731. "PrivateKey": org.private_key,
  732. })))
  733. }
  734. #[derive(Deserialize)]
  735. #[allow(non_snake_case)]
  736. struct CollectionData {
  737. Id: String,
  738. ReadOnly: bool,
  739. HidePasswords: bool,
  740. }
  741. #[derive(Deserialize)]
  742. #[allow(non_snake_case)]
  743. struct InviteData {
  744. Emails: Vec<String>,
  745. Type: NumberOrString,
  746. Collections: Option<Vec<CollectionData>>,
  747. AccessAll: Option<bool>,
  748. }
  749. #[post("/organizations/<org_id>/users/invite", data = "<data>")]
  750. async fn send_invite(
  751. org_id: &str,
  752. data: JsonUpcase<InviteData>,
  753. headers: AdminHeaders,
  754. mut conn: DbConn,
  755. ) -> EmptyResult {
  756. let data: InviteData = data.into_inner().data;
  757. let new_type = match UserOrgType::from_str(&data.Type.into_string()) {
  758. Some(new_type) => new_type as i32,
  759. None => err!("Invalid type"),
  760. };
  761. if new_type != UserOrgType::User && headers.org_user_type != UserOrgType::Owner {
  762. err!("Only Owners can invite Managers, Admins or Owners")
  763. }
  764. for email in data.Emails.iter() {
  765. let email = email.to_lowercase();
  766. let mut user_org_status = UserOrgStatus::Invited as i32;
  767. let user = match User::find_by_mail(&email, &mut conn).await {
  768. None => {
  769. if !CONFIG.invitations_allowed() {
  770. err!(format!("User does not exist: {email}"))
  771. }
  772. if !CONFIG.is_email_domain_allowed(&email) {
  773. err!("Email domain not eligible for invitations")
  774. }
  775. if !CONFIG.mail_enabled() {
  776. let invitation = Invitation::new(&email);
  777. invitation.save(&mut conn).await?;
  778. }
  779. let mut user = User::new(email.clone());
  780. user.save(&mut conn).await?;
  781. user
  782. }
  783. Some(user) => {
  784. if UserOrganization::find_by_user_and_org(&user.uuid, org_id, &mut conn).await.is_some() {
  785. err!(format!("User already in organization: {email}"))
  786. } else {
  787. // automatically accept existing users if mail is disabled
  788. if !CONFIG.mail_enabled() && !user.password_hash.is_empty() {
  789. user_org_status = UserOrgStatus::Accepted as i32;
  790. }
  791. user
  792. }
  793. }
  794. };
  795. let mut new_user = UserOrganization::new(user.uuid.clone(), String::from(org_id));
  796. let access_all = data.AccessAll.unwrap_or(false);
  797. new_user.access_all = access_all;
  798. new_user.atype = new_type;
  799. new_user.status = user_org_status;
  800. // If no accessAll, add the collections received
  801. if !access_all {
  802. for col in data.Collections.iter().flatten() {
  803. match Collection::find_by_uuid_and_org(&col.Id, org_id, &mut conn).await {
  804. None => err!("Collection not found in Organization"),
  805. Some(collection) => {
  806. CollectionUser::save(&user.uuid, &collection.uuid, col.ReadOnly, col.HidePasswords, &mut conn)
  807. .await?;
  808. }
  809. }
  810. }
  811. }
  812. new_user.save(&mut conn).await?;
  813. log_event(
  814. EventType::OrganizationUserInvited as i32,
  815. &new_user.uuid,
  816. org_id,
  817. headers.user.uuid.clone(),
  818. headers.device.atype,
  819. &headers.ip.ip,
  820. &mut conn,
  821. )
  822. .await;
  823. if CONFIG.mail_enabled() {
  824. let org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
  825. Some(org) => org.name,
  826. None => err!("Error looking up organization"),
  827. };
  828. mail::send_invite(
  829. &email,
  830. &user.uuid,
  831. Some(String::from(org_id)),
  832. Some(new_user.uuid),
  833. &org_name,
  834. Some(headers.user.email.clone()),
  835. )
  836. .await?;
  837. }
  838. }
  839. Ok(())
  840. }
  841. #[post("/organizations/<org_id>/users/reinvite", data = "<data>")]
  842. async fn bulk_reinvite_user(
  843. org_id: &str,
  844. data: JsonUpcase<OrgBulkIds>,
  845. headers: AdminHeaders,
  846. mut conn: DbConn,
  847. ) -> Json<Value> {
  848. let data: OrgBulkIds = data.into_inner().data;
  849. let mut bulk_response = Vec::new();
  850. for org_user_id in data.Ids {
  851. let err_msg = match _reinvite_user(org_id, &org_user_id, &headers.user.email, &mut conn).await {
  852. Ok(_) => String::new(),
  853. Err(e) => format!("{e:?}"),
  854. };
  855. bulk_response.push(json!(
  856. {
  857. "Object": "OrganizationBulkConfirmResponseModel",
  858. "Id": org_user_id,
  859. "Error": err_msg
  860. }
  861. ))
  862. }
  863. Json(json!({
  864. "Data": bulk_response,
  865. "Object": "list",
  866. "ContinuationToken": null
  867. }))
  868. }
  869. #[post("/organizations/<org_id>/users/<user_org>/reinvite")]
  870. async fn reinvite_user(org_id: &str, user_org: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
  871. _reinvite_user(org_id, user_org, &headers.user.email, &mut conn).await
  872. }
  873. async fn _reinvite_user(org_id: &str, user_org: &str, invited_by_email: &str, conn: &mut DbConn) -> EmptyResult {
  874. if !CONFIG.invitations_allowed() {
  875. err!("Invitations are not allowed.")
  876. }
  877. if !CONFIG.mail_enabled() {
  878. err!("SMTP is not configured.")
  879. }
  880. let user_org = match UserOrganization::find_by_uuid(user_org, conn).await {
  881. Some(user_org) => user_org,
  882. None => err!("The user hasn't been invited to the organization."),
  883. };
  884. if user_org.status != UserOrgStatus::Invited as i32 {
  885. err!("The user is already accepted or confirmed to the organization")
  886. }
  887. let user = match User::find_by_uuid(&user_org.user_uuid, conn).await {
  888. Some(user) => user,
  889. None => err!("User not found."),
  890. };
  891. let org_name = match Organization::find_by_uuid(org_id, conn).await {
  892. Some(org) => org.name,
  893. None => err!("Error looking up organization."),
  894. };
  895. if CONFIG.mail_enabled() {
  896. mail::send_invite(
  897. &user.email,
  898. &user.uuid,
  899. Some(org_id.to_string()),
  900. Some(user_org.uuid),
  901. &org_name,
  902. Some(invited_by_email.to_string()),
  903. )
  904. .await?;
  905. } else {
  906. let invitation = Invitation::new(&user.email);
  907. invitation.save(conn).await?;
  908. }
  909. Ok(())
  910. }
  911. #[derive(Deserialize)]
  912. #[allow(non_snake_case)]
  913. struct AcceptData {
  914. Token: String,
  915. ResetPasswordKey: Option<String>,
  916. }
  917. #[post("/organizations/<org_id>/users/<_org_user_id>/accept", data = "<data>")]
  918. async fn accept_invite(
  919. org_id: &str,
  920. _org_user_id: &str,
  921. data: JsonUpcase<AcceptData>,
  922. mut conn: DbConn,
  923. ) -> EmptyResult {
  924. // The web-vault passes org_id and org_user_id in the URL, but we are just reading them from the JWT instead
  925. let data: AcceptData = data.into_inner().data;
  926. let claims = decode_invite(&data.Token)?;
  927. match User::find_by_mail(&claims.email, &mut conn).await {
  928. Some(_) => {
  929. Invitation::take(&claims.email, &mut conn).await;
  930. if let (Some(user_org), Some(org)) = (&claims.user_org_id, &claims.org_id) {
  931. let mut user_org = match UserOrganization::find_by_uuid_and_org(user_org, org, &mut conn).await {
  932. Some(user_org) => user_org,
  933. None => err!("Error accepting the invitation"),
  934. };
  935. if user_org.status != UserOrgStatus::Invited as i32 {
  936. err!("User already accepted the invitation")
  937. }
  938. let master_password_required = OrgPolicy::org_is_reset_password_auto_enroll(org, &mut conn).await;
  939. if data.ResetPasswordKey.is_none() && master_password_required {
  940. err!("Reset password key is required, but not provided.");
  941. }
  942. // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type
  943. // It returns different error messages per function.
  944. if user_org.atype < UserOrgType::Admin {
  945. match OrgPolicy::is_user_allowed(&user_org.user_uuid, org_id, false, &mut conn).await {
  946. Ok(_) => {}
  947. Err(OrgPolicyErr::TwoFactorMissing) => {
  948. err!("You cannot join this organization until you enable two-step login on your user account");
  949. }
  950. Err(OrgPolicyErr::SingleOrgEnforced) => {
  951. err!("You cannot join this organization because you are a member of an organization which forbids it");
  952. }
  953. }
  954. }
  955. user_org.status = UserOrgStatus::Accepted as i32;
  956. if master_password_required {
  957. user_org.reset_password_key = data.ResetPasswordKey;
  958. }
  959. user_org.save(&mut conn).await?;
  960. }
  961. }
  962. None => err!("Invited user not found"),
  963. }
  964. if CONFIG.mail_enabled() {
  965. let mut org_name = CONFIG.invitation_org_name();
  966. if let Some(org_id) = &claims.org_id {
  967. org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
  968. Some(org) => org.name,
  969. None => err!("Organization not found."),
  970. };
  971. };
  972. if let Some(invited_by_email) = &claims.invited_by_email {
  973. // User was invited to an organization, so they must be confirmed manually after acceptance
  974. mail::send_invite_accepted(&claims.email, invited_by_email, &org_name).await?;
  975. } else {
  976. // User was invited from /admin, so they are automatically confirmed
  977. mail::send_invite_confirmed(&claims.email, &org_name).await?;
  978. }
  979. }
  980. Ok(())
  981. }
  982. #[post("/organizations/<org_id>/users/confirm", data = "<data>")]
  983. async fn bulk_confirm_invite(
  984. org_id: &str,
  985. data: JsonUpcase<Value>,
  986. headers: AdminHeaders,
  987. mut conn: DbConn,
  988. nt: Notify<'_>,
  989. ) -> Json<Value> {
  990. let data = data.into_inner().data;
  991. let mut bulk_response = Vec::new();
  992. match data["Keys"].as_array() {
  993. Some(keys) => {
  994. for invite in keys {
  995. let org_user_id = invite["Id"].as_str().unwrap_or_default();
  996. let user_key = invite["Key"].as_str().unwrap_or_default();
  997. let err_msg = match _confirm_invite(org_id, org_user_id, user_key, &headers, &mut conn, &nt).await {
  998. Ok(_) => String::new(),
  999. Err(e) => format!("{e:?}"),
  1000. };
  1001. bulk_response.push(json!(
  1002. {
  1003. "Object": "OrganizationBulkConfirmResponseModel",
  1004. "Id": org_user_id,
  1005. "Error": err_msg
  1006. }
  1007. ));
  1008. }
  1009. }
  1010. None => error!("No keys to confirm"),
  1011. }
  1012. Json(json!({
  1013. "Data": bulk_response,
  1014. "Object": "list",
  1015. "ContinuationToken": null
  1016. }))
  1017. }
  1018. #[post("/organizations/<org_id>/users/<org_user_id>/confirm", data = "<data>")]
  1019. async fn confirm_invite(
  1020. org_id: &str,
  1021. org_user_id: &str,
  1022. data: JsonUpcase<Value>,
  1023. headers: AdminHeaders,
  1024. mut conn: DbConn,
  1025. nt: Notify<'_>,
  1026. ) -> EmptyResult {
  1027. let data = data.into_inner().data;
  1028. let user_key = data["Key"].as_str().unwrap_or_default();
  1029. _confirm_invite(org_id, org_user_id, user_key, &headers, &mut conn, &nt).await
  1030. }
  1031. async fn _confirm_invite(
  1032. org_id: &str,
  1033. org_user_id: &str,
  1034. key: &str,
  1035. headers: &AdminHeaders,
  1036. conn: &mut DbConn,
  1037. nt: &Notify<'_>,
  1038. ) -> EmptyResult {
  1039. if key.is_empty() || org_user_id.is_empty() {
  1040. err!("Key or UserId is not set, unable to process request");
  1041. }
  1042. let mut user_to_confirm = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
  1043. Some(user) => user,
  1044. None => err!("The specified user isn't a member of the organization"),
  1045. };
  1046. if user_to_confirm.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner {
  1047. err!("Only Owners can confirm Managers, Admins or Owners")
  1048. }
  1049. if user_to_confirm.status != UserOrgStatus::Accepted as i32 {
  1050. err!("User in invalid state")
  1051. }
  1052. // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type
  1053. // It returns different error messages per function.
  1054. if user_to_confirm.atype < UserOrgType::Admin {
  1055. match OrgPolicy::is_user_allowed(&user_to_confirm.user_uuid, org_id, true, conn).await {
  1056. Ok(_) => {}
  1057. Err(OrgPolicyErr::TwoFactorMissing) => {
  1058. err!("You cannot confirm this user because it has no two-step login method activated");
  1059. }
  1060. Err(OrgPolicyErr::SingleOrgEnforced) => {
  1061. err!("You cannot confirm this user because it is a member of an organization which forbids it");
  1062. }
  1063. }
  1064. }
  1065. user_to_confirm.status = UserOrgStatus::Confirmed as i32;
  1066. user_to_confirm.akey = key.to_string();
  1067. log_event(
  1068. EventType::OrganizationUserConfirmed as i32,
  1069. &user_to_confirm.uuid,
  1070. org_id,
  1071. headers.user.uuid.clone(),
  1072. headers.device.atype,
  1073. &headers.ip.ip,
  1074. conn,
  1075. )
  1076. .await;
  1077. if CONFIG.mail_enabled() {
  1078. let org_name = match Organization::find_by_uuid(org_id, conn).await {
  1079. Some(org) => org.name,
  1080. None => err!("Error looking up organization."),
  1081. };
  1082. let address = match User::find_by_uuid(&user_to_confirm.user_uuid, conn).await {
  1083. Some(user) => user.email,
  1084. None => err!("Error looking up user."),
  1085. };
  1086. mail::send_invite_confirmed(&address, &org_name).await?;
  1087. }
  1088. let save_result = user_to_confirm.save(conn).await;
  1089. if let Some(user) = User::find_by_uuid(&user_to_confirm.user_uuid, conn).await {
  1090. nt.send_user_update(UpdateType::SyncOrgKeys, &user).await;
  1091. }
  1092. save_result
  1093. }
  1094. #[get("/organizations/<org_id>/users/<org_user_id>?<data..>")]
  1095. async fn get_user(
  1096. org_id: &str,
  1097. org_user_id: &str,
  1098. data: GetOrgUserData,
  1099. _headers: AdminHeaders,
  1100. mut conn: DbConn,
  1101. ) -> JsonResult {
  1102. let user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
  1103. Some(user) => user,
  1104. None => err!("The specified user isn't a member of the organization"),
  1105. };
  1106. // In this case, when groups are requested we also need to include collections.
  1107. // Else these will not be shown in the interface, and could lead to missing collections when saved.
  1108. let include_groups = data.include_groups.unwrap_or(false);
  1109. Ok(Json(
  1110. user.to_json_user_details(data.include_collections.unwrap_or(include_groups), include_groups, &mut conn).await,
  1111. ))
  1112. }
  1113. #[derive(Deserialize)]
  1114. #[allow(non_snake_case)]
  1115. struct EditUserData {
  1116. Type: NumberOrString,
  1117. Collections: Option<Vec<CollectionData>>,
  1118. Groups: Option<Vec<String>>,
  1119. AccessAll: bool,
  1120. }
  1121. #[put("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)]
  1122. async fn put_organization_user(
  1123. org_id: &str,
  1124. org_user_id: &str,
  1125. data: JsonUpcase<EditUserData>,
  1126. headers: AdminHeaders,
  1127. conn: DbConn,
  1128. ) -> EmptyResult {
  1129. edit_user(org_id, org_user_id, data, headers, conn).await
  1130. }
  1131. #[post("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)]
  1132. async fn edit_user(
  1133. org_id: &str,
  1134. org_user_id: &str,
  1135. data: JsonUpcase<EditUserData>,
  1136. headers: AdminHeaders,
  1137. mut conn: DbConn,
  1138. ) -> EmptyResult {
  1139. let data: EditUserData = data.into_inner().data;
  1140. let new_type = match UserOrgType::from_str(&data.Type.into_string()) {
  1141. Some(new_type) => new_type,
  1142. None => err!("Invalid type"),
  1143. };
  1144. let mut user_to_edit = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
  1145. Some(user) => user,
  1146. None => err!("The specified user isn't member of the organization"),
  1147. };
  1148. if new_type != user_to_edit.atype
  1149. && (user_to_edit.atype >= UserOrgType::Admin || new_type >= UserOrgType::Admin)
  1150. && headers.org_user_type != UserOrgType::Owner
  1151. {
  1152. err!("Only Owners can grant and remove Admin or Owner privileges")
  1153. }
  1154. if user_to_edit.atype == UserOrgType::Owner && headers.org_user_type != UserOrgType::Owner {
  1155. err!("Only Owners can edit Owner users")
  1156. }
  1157. if user_to_edit.atype == UserOrgType::Owner
  1158. && new_type != UserOrgType::Owner
  1159. && user_to_edit.status == UserOrgStatus::Confirmed as i32
  1160. {
  1161. // Removing owner permission, check that there is at least one other confirmed owner
  1162. if UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, &mut conn).await <= 1 {
  1163. err!("Can't delete the last owner")
  1164. }
  1165. }
  1166. // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type
  1167. // It returns different error messages per function.
  1168. if new_type < UserOrgType::Admin {
  1169. match OrgPolicy::is_user_allowed(&user_to_edit.user_uuid, org_id, true, &mut conn).await {
  1170. Ok(_) => {}
  1171. Err(OrgPolicyErr::TwoFactorMissing) => {
  1172. err!("You cannot modify this user to this type because it has no two-step login method activated");
  1173. }
  1174. Err(OrgPolicyErr::SingleOrgEnforced) => {
  1175. err!("You cannot modify this user to this type because it is a member of an organization which forbids it");
  1176. }
  1177. }
  1178. }
  1179. user_to_edit.access_all = data.AccessAll;
  1180. user_to_edit.atype = new_type as i32;
  1181. // Delete all the odd collections
  1182. for c in CollectionUser::find_by_organization_and_user_uuid(org_id, &user_to_edit.user_uuid, &mut conn).await {
  1183. c.delete(&mut conn).await?;
  1184. }
  1185. // If no accessAll, add the collections received
  1186. if !data.AccessAll {
  1187. for col in data.Collections.iter().flatten() {
  1188. match Collection::find_by_uuid_and_org(&col.Id, org_id, &mut conn).await {
  1189. None => err!("Collection not found in Organization"),
  1190. Some(collection) => {
  1191. CollectionUser::save(
  1192. &user_to_edit.user_uuid,
  1193. &collection.uuid,
  1194. col.ReadOnly,
  1195. col.HidePasswords,
  1196. &mut conn,
  1197. )
  1198. .await?;
  1199. }
  1200. }
  1201. }
  1202. }
  1203. GroupUser::delete_all_by_user(&user_to_edit.uuid, &mut conn).await?;
  1204. for group in data.Groups.iter().flatten() {
  1205. let mut group_entry = GroupUser::new(String::from(group), user_to_edit.uuid.clone());
  1206. group_entry.save(&mut conn).await?;
  1207. }
  1208. log_event(
  1209. EventType::OrganizationUserUpdated as i32,
  1210. &user_to_edit.uuid,
  1211. org_id,
  1212. headers.user.uuid.clone(),
  1213. headers.device.atype,
  1214. &headers.ip.ip,
  1215. &mut conn,
  1216. )
  1217. .await;
  1218. user_to_edit.save(&mut conn).await
  1219. }
  1220. #[delete("/organizations/<org_id>/users", data = "<data>")]
  1221. async fn bulk_delete_user(
  1222. org_id: &str,
  1223. data: JsonUpcase<OrgBulkIds>,
  1224. headers: AdminHeaders,
  1225. mut conn: DbConn,
  1226. nt: Notify<'_>,
  1227. ) -> Json<Value> {
  1228. let data: OrgBulkIds = data.into_inner().data;
  1229. let mut bulk_response = Vec::new();
  1230. for org_user_id in data.Ids {
  1231. let err_msg = match _delete_user(org_id, &org_user_id, &headers, &mut conn, &nt).await {
  1232. Ok(_) => String::new(),
  1233. Err(e) => format!("{e:?}"),
  1234. };
  1235. bulk_response.push(json!(
  1236. {
  1237. "Object": "OrganizationBulkConfirmResponseModel",
  1238. "Id": org_user_id,
  1239. "Error": err_msg
  1240. }
  1241. ))
  1242. }
  1243. Json(json!({
  1244. "Data": bulk_response,
  1245. "Object": "list",
  1246. "ContinuationToken": null
  1247. }))
  1248. }
  1249. #[delete("/organizations/<org_id>/users/<org_user_id>")]
  1250. async fn delete_user(
  1251. org_id: &str,
  1252. org_user_id: &str,
  1253. headers: AdminHeaders,
  1254. mut conn: DbConn,
  1255. nt: Notify<'_>,
  1256. ) -> EmptyResult {
  1257. _delete_user(org_id, org_user_id, &headers, &mut conn, &nt).await
  1258. }
  1259. #[post("/organizations/<org_id>/users/<org_user_id>/delete")]
  1260. async fn post_delete_user(
  1261. org_id: &str,
  1262. org_user_id: &str,
  1263. headers: AdminHeaders,
  1264. mut conn: DbConn,
  1265. nt: Notify<'_>,
  1266. ) -> EmptyResult {
  1267. _delete_user(org_id, org_user_id, &headers, &mut conn, &nt).await
  1268. }
  1269. async fn _delete_user(
  1270. org_id: &str,
  1271. org_user_id: &str,
  1272. headers: &AdminHeaders,
  1273. conn: &mut DbConn,
  1274. nt: &Notify<'_>,
  1275. ) -> EmptyResult {
  1276. let user_to_delete = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
  1277. Some(user) => user,
  1278. None => err!("User to delete isn't member of the organization"),
  1279. };
  1280. if user_to_delete.atype != UserOrgType::User && headers.org_user_type != UserOrgType::Owner {
  1281. err!("Only Owners can delete Admins or Owners")
  1282. }
  1283. if user_to_delete.atype == UserOrgType::Owner && user_to_delete.status == UserOrgStatus::Confirmed as i32 {
  1284. // Removing owner, check that there is at least one other confirmed owner
  1285. if UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, conn).await <= 1 {
  1286. err!("Can't delete the last owner")
  1287. }
  1288. }
  1289. log_event(
  1290. EventType::OrganizationUserRemoved as i32,
  1291. &user_to_delete.uuid,
  1292. org_id,
  1293. headers.user.uuid.clone(),
  1294. headers.device.atype,
  1295. &headers.ip.ip,
  1296. conn,
  1297. )
  1298. .await;
  1299. if let Some(user) = User::find_by_uuid(&user_to_delete.user_uuid, conn).await {
  1300. nt.send_user_update(UpdateType::SyncOrgKeys, &user).await;
  1301. }
  1302. user_to_delete.delete(conn).await
  1303. }
  1304. #[post("/organizations/<org_id>/users/public-keys", data = "<data>")]
  1305. async fn bulk_public_keys(
  1306. org_id: &str,
  1307. data: JsonUpcase<OrgBulkIds>,
  1308. _headers: AdminHeaders,
  1309. mut conn: DbConn,
  1310. ) -> Json<Value> {
  1311. let data: OrgBulkIds = data.into_inner().data;
  1312. let mut bulk_response = Vec::new();
  1313. // Check all received UserOrg UUID's and find the matching User to retreive the public-key.
  1314. // If the user does not exists, just ignore it, and do not return any information regarding that UserOrg UUID.
  1315. // The web-vault will then ignore that user for the folowing steps.
  1316. for user_org_id in data.Ids {
  1317. match UserOrganization::find_by_uuid_and_org(&user_org_id, org_id, &mut conn).await {
  1318. Some(user_org) => match User::find_by_uuid(&user_org.user_uuid, &mut conn).await {
  1319. Some(user) => bulk_response.push(json!(
  1320. {
  1321. "Object": "organizationUserPublicKeyResponseModel",
  1322. "Id": user_org_id,
  1323. "UserId": user.uuid,
  1324. "Key": user.public_key
  1325. }
  1326. )),
  1327. None => debug!("User doesn't exist"),
  1328. },
  1329. None => debug!("UserOrg doesn't exist"),
  1330. }
  1331. }
  1332. Json(json!({
  1333. "Data": bulk_response,
  1334. "Object": "list",
  1335. "ContinuationToken": null
  1336. }))
  1337. }
  1338. use super::ciphers::update_cipher_from_data;
  1339. use super::ciphers::CipherData;
  1340. #[derive(Deserialize)]
  1341. #[allow(non_snake_case)]
  1342. struct ImportData {
  1343. Ciphers: Vec<CipherData>,
  1344. Collections: Vec<NewCollectionData>,
  1345. CollectionRelationships: Vec<RelationsData>,
  1346. }
  1347. #[derive(Deserialize)]
  1348. #[allow(non_snake_case)]
  1349. struct RelationsData {
  1350. // Cipher index
  1351. Key: usize,
  1352. // Collection index
  1353. Value: usize,
  1354. }
  1355. #[post("/ciphers/import-organization?<query..>", data = "<data>")]
  1356. async fn post_org_import(
  1357. query: OrgIdData,
  1358. data: JsonUpcase<ImportData>,
  1359. headers: AdminHeaders,
  1360. mut conn: DbConn,
  1361. nt: Notify<'_>,
  1362. ) -> EmptyResult {
  1363. let data: ImportData = data.into_inner().data;
  1364. let org_id = query.organization_id;
  1365. // Validate the import before continuing
  1366. // Bitwarden does not process the import if there is one item invalid.
  1367. // Since we check for the size of the encrypted note length, we need to do that here to pre-validate it.
  1368. // TODO: See if we can optimize the whole cipher adding/importing and prevent duplicate code and checks.
  1369. Cipher::validate_notes(&data.Ciphers)?;
  1370. let mut collections = Vec::new();
  1371. for coll in data.Collections {
  1372. let collection = Collection::new(org_id.clone(), coll.Name);
  1373. if collection.save(&mut conn).await.is_err() {
  1374. collections.push(Err(Error::new("Failed to create Collection", "Failed to create Collection")));
  1375. } else {
  1376. collections.push(Ok(collection));
  1377. }
  1378. }
  1379. // Read the relations between collections and ciphers
  1380. let mut relations = Vec::new();
  1381. for relation in data.CollectionRelationships {
  1382. relations.push((relation.Key, relation.Value));
  1383. }
  1384. let headers: Headers = headers.into();
  1385. let mut ciphers = Vec::new();
  1386. for cipher_data in data.Ciphers {
  1387. let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone());
  1388. update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &mut conn, &nt, UpdateType::None).await.ok();
  1389. ciphers.push(cipher);
  1390. }
  1391. // Assign the collections
  1392. for (cipher_index, coll_index) in relations {
  1393. let cipher_id = &ciphers[cipher_index].uuid;
  1394. let coll = &collections[coll_index];
  1395. let coll_id = match coll {
  1396. Ok(coll) => coll.uuid.as_str(),
  1397. Err(_) => err!("Failed to assign to collection"),
  1398. };
  1399. CollectionCipher::save(cipher_id, coll_id, &mut conn).await?;
  1400. }
  1401. let mut user = headers.user;
  1402. user.update_revision(&mut conn).await
  1403. }
  1404. #[get("/organizations/<org_id>/policies")]
  1405. async fn list_policies(org_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> Json<Value> {
  1406. let policies = OrgPolicy::find_by_org(org_id, &mut conn).await;
  1407. let policies_json: Vec<Value> = policies.iter().map(OrgPolicy::to_json).collect();
  1408. Json(json!({
  1409. "Data": policies_json,
  1410. "Object": "list",
  1411. "ContinuationToken": null
  1412. }))
  1413. }
  1414. #[get("/organizations/<org_id>/policies/token?<token>")]
  1415. async fn list_policies_token(org_id: &str, token: &str, mut conn: DbConn) -> JsonResult {
  1416. let invite = crate::auth::decode_invite(token)?;
  1417. let invite_org_id = match invite.org_id {
  1418. Some(invite_org_id) => invite_org_id,
  1419. None => err!("Invalid token"),
  1420. };
  1421. if invite_org_id != org_id {
  1422. err!("Token doesn't match request organization");
  1423. }
  1424. // TODO: We receive the invite token as ?token=<>, validate it contains the org id
  1425. let policies = OrgPolicy::find_by_org(org_id, &mut conn).await;
  1426. let policies_json: Vec<Value> = policies.iter().map(OrgPolicy::to_json).collect();
  1427. Ok(Json(json!({
  1428. "Data": policies_json,
  1429. "Object": "list",
  1430. "ContinuationToken": null
  1431. })))
  1432. }
  1433. #[get("/organizations/<org_id>/policies/<pol_type>")]
  1434. async fn get_policy(org_id: &str, pol_type: i32, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
  1435. let pol_type_enum = match OrgPolicyType::from_i32(pol_type) {
  1436. Some(pt) => pt,
  1437. None => err!("Invalid or unsupported policy type"),
  1438. };
  1439. let policy = match OrgPolicy::find_by_org_and_type(org_id, pol_type_enum, &mut conn).await {
  1440. Some(p) => p,
  1441. None => OrgPolicy::new(String::from(org_id), pol_type_enum, "null".to_string()),
  1442. };
  1443. Ok(Json(policy.to_json()))
  1444. }
  1445. #[derive(Deserialize)]
  1446. struct PolicyData {
  1447. enabled: bool,
  1448. #[serde(rename = "type")]
  1449. _type: i32,
  1450. data: Option<Value>,
  1451. }
  1452. #[put("/organizations/<org_id>/policies/<pol_type>", data = "<data>")]
  1453. async fn put_policy(
  1454. org_id: &str,
  1455. pol_type: i32,
  1456. data: Json<PolicyData>,
  1457. headers: AdminHeaders,
  1458. mut conn: DbConn,
  1459. ) -> JsonResult {
  1460. let data: PolicyData = data.into_inner();
  1461. let pol_type_enum = match OrgPolicyType::from_i32(pol_type) {
  1462. Some(pt) => pt,
  1463. None => err!("Invalid or unsupported policy type"),
  1464. };
  1465. // When enabling the TwoFactorAuthentication policy, remove this org's members that do have 2FA
  1466. if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled {
  1467. for member in UserOrganization::find_by_org(org_id, &mut conn).await.into_iter() {
  1468. let user_twofactor_disabled = TwoFactor::find_by_user(&member.user_uuid, &mut conn).await.is_empty();
  1469. // Policy only applies to non-Owner/non-Admin members who have accepted joining the org
  1470. // Invited users still need to accept the invite and will get an error when they try to accept the invite.
  1471. if user_twofactor_disabled
  1472. && member.atype < UserOrgType::Admin
  1473. && member.status != UserOrgStatus::Invited as i32
  1474. {
  1475. if CONFIG.mail_enabled() {
  1476. let org = Organization::find_by_uuid(&member.org_uuid, &mut conn).await.unwrap();
  1477. let user = User::find_by_uuid(&member.user_uuid, &mut conn).await.unwrap();
  1478. mail::send_2fa_removed_from_org(&user.email, &org.name).await?;
  1479. }
  1480. log_event(
  1481. EventType::OrganizationUserRemoved as i32,
  1482. &member.uuid,
  1483. org_id,
  1484. headers.user.uuid.clone(),
  1485. headers.device.atype,
  1486. &headers.ip.ip,
  1487. &mut conn,
  1488. )
  1489. .await;
  1490. member.delete(&mut conn).await?;
  1491. }
  1492. }
  1493. }
  1494. // When enabling the SingleOrg policy, remove this org's members that are members of other orgs
  1495. if pol_type_enum == OrgPolicyType::SingleOrg && data.enabled {
  1496. for member in UserOrganization::find_by_org(org_id, &mut conn).await.into_iter() {
  1497. // Policy only applies to non-Owner/non-Admin members who have accepted joining the org
  1498. // Exclude invited and revoked users when checking for this policy.
  1499. // Those users will not be allowed to accept or be activated because of the policy checks done there.
  1500. // We check if the count is larger then 1, because it includes this organization also.
  1501. if member.atype < UserOrgType::Admin
  1502. && member.status != UserOrgStatus::Invited as i32
  1503. && UserOrganization::count_accepted_and_confirmed_by_user(&member.user_uuid, &mut conn).await > 1
  1504. {
  1505. if CONFIG.mail_enabled() {
  1506. let org = Organization::find_by_uuid(&member.org_uuid, &mut conn).await.unwrap();
  1507. let user = User::find_by_uuid(&member.user_uuid, &mut conn).await.unwrap();
  1508. mail::send_single_org_removed_from_org(&user.email, &org.name).await?;
  1509. }
  1510. log_event(
  1511. EventType::OrganizationUserRemoved as i32,
  1512. &member.uuid,
  1513. org_id,
  1514. headers.user.uuid.clone(),
  1515. headers.device.atype,
  1516. &headers.ip.ip,
  1517. &mut conn,
  1518. )
  1519. .await;
  1520. member.delete(&mut conn).await?;
  1521. }
  1522. }
  1523. }
  1524. let mut policy = match OrgPolicy::find_by_org_and_type(org_id, pol_type_enum, &mut conn).await {
  1525. Some(p) => p,
  1526. None => OrgPolicy::new(String::from(org_id), pol_type_enum, "{}".to_string()),
  1527. };
  1528. policy.enabled = data.enabled;
  1529. policy.data = serde_json::to_string(&data.data)?;
  1530. policy.save(&mut conn).await?;
  1531. log_event(
  1532. EventType::PolicyUpdated as i32,
  1533. &policy.uuid,
  1534. org_id,
  1535. headers.user.uuid.clone(),
  1536. headers.device.atype,
  1537. &headers.ip.ip,
  1538. &mut conn,
  1539. )
  1540. .await;
  1541. Ok(Json(policy.to_json()))
  1542. }
  1543. #[allow(unused_variables)]
  1544. #[get("/organizations/<org_id>/tax")]
  1545. fn get_organization_tax(org_id: &str, _headers: Headers) -> Json<Value> {
  1546. // Prevent a 404 error, which also causes Javascript errors.
  1547. // Upstream sends "Only allowed when not self hosted." As an error message.
  1548. // If we do the same it will also output this to the log, which is overkill.
  1549. // An empty list/data also works fine.
  1550. Json(_empty_data_json())
  1551. }
  1552. #[get("/plans")]
  1553. fn get_plans() -> Json<Value> {
  1554. // Respond with a minimal json just enough to allow the creation of an new organization.
  1555. Json(json!({
  1556. "Object": "list",
  1557. "Data": [{
  1558. "Object": "plan",
  1559. "Type": 0,
  1560. "Product": 0,
  1561. "Name": "Free",
  1562. "NameLocalizationKey": "planNameFree",
  1563. "DescriptionLocalizationKey": "planDescFree"
  1564. }],
  1565. "ContinuationToken": null
  1566. }))
  1567. }
  1568. #[get("/plans/sales-tax-rates")]
  1569. fn get_plans_tax_rates(_headers: Headers) -> Json<Value> {
  1570. // Prevent a 404 error, which also causes Javascript errors.
  1571. Json(_empty_data_json())
  1572. }
  1573. fn _empty_data_json() -> Value {
  1574. json!({
  1575. "Object": "list",
  1576. "Data": [],
  1577. "ContinuationToken": null
  1578. })
  1579. }
  1580. #[derive(Deserialize, Debug)]
  1581. #[allow(non_snake_case, dead_code)]
  1582. struct OrgImportGroupData {
  1583. Name: String, // "GroupName"
  1584. ExternalId: String, // "cn=GroupName,ou=Groups,dc=example,dc=com"
  1585. Users: Vec<String>, // ["uid=user,ou=People,dc=example,dc=com"]
  1586. }
  1587. #[derive(Deserialize, Debug)]
  1588. #[allow(non_snake_case)]
  1589. struct OrgImportUserData {
  1590. Email: String, // "[email protected]"
  1591. #[allow(dead_code)]
  1592. ExternalId: String, // "uid=user,ou=People,dc=example,dc=com"
  1593. Deleted: bool,
  1594. }
  1595. #[derive(Deserialize, Debug)]
  1596. #[allow(non_snake_case)]
  1597. struct OrgImportData {
  1598. #[allow(dead_code)]
  1599. Groups: Vec<OrgImportGroupData>,
  1600. OverwriteExisting: bool,
  1601. Users: Vec<OrgImportUserData>,
  1602. }
  1603. #[post("/organizations/<org_id>/import", data = "<data>")]
  1604. async fn import(org_id: &str, data: JsonUpcase<OrgImportData>, headers: Headers, mut conn: DbConn) -> EmptyResult {
  1605. let data = data.into_inner().data;
  1606. // TODO: Currently we aren't storing the externalId's anywhere, so we also don't have a way
  1607. // to differentiate between auto-imported users and manually added ones.
  1608. // This means that this endpoint can end up removing users that were added manually by an admin,
  1609. // as opposed to upstream which only removes auto-imported users.
  1610. // User needs to be admin or owner to use the Directry Connector
  1611. match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
  1612. Some(user_org) if user_org.atype >= UserOrgType::Admin => { /* Okay, nothing to do */ }
  1613. Some(_) => err!("User has insufficient permissions to use Directory Connector"),
  1614. None => err!("User not part of organization"),
  1615. };
  1616. for user_data in &data.Users {
  1617. if user_data.Deleted {
  1618. // If user is marked for deletion and it exists, delete it
  1619. if let Some(user_org) = UserOrganization::find_by_email_and_org(&user_data.Email, org_id, &mut conn).await {
  1620. log_event(
  1621. EventType::OrganizationUserRemoved as i32,
  1622. &user_org.uuid,
  1623. org_id,
  1624. headers.user.uuid.clone(),
  1625. headers.device.atype,
  1626. &headers.ip.ip,
  1627. &mut conn,
  1628. )
  1629. .await;
  1630. user_org.delete(&mut conn).await?;
  1631. }
  1632. // If user is not part of the organization, but it exists
  1633. } else if UserOrganization::find_by_email_and_org(&user_data.Email, org_id, &mut conn).await.is_none() {
  1634. if let Some(user) = User::find_by_mail(&user_data.Email, &mut conn).await {
  1635. let user_org_status = if CONFIG.mail_enabled() {
  1636. UserOrgStatus::Invited as i32
  1637. } else {
  1638. UserOrgStatus::Accepted as i32 // Automatically mark user as accepted if no email invites
  1639. };
  1640. let mut new_org_user = UserOrganization::new(user.uuid.clone(), String::from(org_id));
  1641. new_org_user.access_all = false;
  1642. new_org_user.atype = UserOrgType::User as i32;
  1643. new_org_user.status = user_org_status;
  1644. new_org_user.save(&mut conn).await?;
  1645. log_event(
  1646. EventType::OrganizationUserInvited as i32,
  1647. &new_org_user.uuid,
  1648. org_id,
  1649. headers.user.uuid.clone(),
  1650. headers.device.atype,
  1651. &headers.ip.ip,
  1652. &mut conn,
  1653. )
  1654. .await;
  1655. if CONFIG.mail_enabled() {
  1656. let org_name = match Organization::find_by_uuid(org_id, &mut conn).await {
  1657. Some(org) => org.name,
  1658. None => err!("Error looking up organization"),
  1659. };
  1660. mail::send_invite(
  1661. &user_data.Email,
  1662. &user.uuid,
  1663. Some(String::from(org_id)),
  1664. Some(new_org_user.uuid),
  1665. &org_name,
  1666. Some(headers.user.email.clone()),
  1667. )
  1668. .await?;
  1669. }
  1670. }
  1671. }
  1672. }
  1673. // If this flag is enabled, any user that isn't provided in the Users list will be removed (by default they will be kept unless they have Deleted == true)
  1674. if data.OverwriteExisting {
  1675. for user_org in UserOrganization::find_by_org_and_type(org_id, UserOrgType::User, &mut conn).await {
  1676. if let Some(user_email) = User::find_by_uuid(&user_org.user_uuid, &mut conn).await.map(|u| u.email) {
  1677. if !data.Users.iter().any(|u| u.Email == user_email) {
  1678. log_event(
  1679. EventType::OrganizationUserRemoved as i32,
  1680. &user_org.uuid,
  1681. org_id,
  1682. headers.user.uuid.clone(),
  1683. headers.device.atype,
  1684. &headers.ip.ip,
  1685. &mut conn,
  1686. )
  1687. .await;
  1688. user_org.delete(&mut conn).await?;
  1689. }
  1690. }
  1691. }
  1692. }
  1693. Ok(())
  1694. }
  1695. // Pre web-vault v2022.9.x endpoint
  1696. #[put("/organizations/<org_id>/users/<org_user_id>/deactivate")]
  1697. async fn deactivate_organization_user(
  1698. org_id: &str,
  1699. org_user_id: &str,
  1700. headers: AdminHeaders,
  1701. mut conn: DbConn,
  1702. ) -> EmptyResult {
  1703. _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await
  1704. }
  1705. // Pre web-vault v2022.9.x endpoint
  1706. #[put("/organizations/<org_id>/users/deactivate", data = "<data>")]
  1707. async fn bulk_deactivate_organization_user(
  1708. org_id: &str,
  1709. data: JsonUpcase<Value>,
  1710. headers: AdminHeaders,
  1711. conn: DbConn,
  1712. ) -> Json<Value> {
  1713. bulk_revoke_organization_user(org_id, data, headers, conn).await
  1714. }
  1715. #[put("/organizations/<org_id>/users/<org_user_id>/revoke")]
  1716. async fn revoke_organization_user(
  1717. org_id: &str,
  1718. org_user_id: &str,
  1719. headers: AdminHeaders,
  1720. mut conn: DbConn,
  1721. ) -> EmptyResult {
  1722. _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await
  1723. }
  1724. #[put("/organizations/<org_id>/users/revoke", data = "<data>")]
  1725. async fn bulk_revoke_organization_user(
  1726. org_id: &str,
  1727. data: JsonUpcase<Value>,
  1728. headers: AdminHeaders,
  1729. mut conn: DbConn,
  1730. ) -> Json<Value> {
  1731. let data = data.into_inner().data;
  1732. let mut bulk_response = Vec::new();
  1733. match data["Ids"].as_array() {
  1734. Some(org_users) => {
  1735. for org_user_id in org_users {
  1736. let org_user_id = org_user_id.as_str().unwrap_or_default();
  1737. let err_msg = match _revoke_organization_user(org_id, org_user_id, &headers, &mut conn).await {
  1738. Ok(_) => String::new(),
  1739. Err(e) => format!("{e:?}"),
  1740. };
  1741. bulk_response.push(json!(
  1742. {
  1743. "Object": "OrganizationUserBulkResponseModel",
  1744. "Id": org_user_id,
  1745. "Error": err_msg
  1746. }
  1747. ));
  1748. }
  1749. }
  1750. None => error!("No users to revoke"),
  1751. }
  1752. Json(json!({
  1753. "Data": bulk_response,
  1754. "Object": "list",
  1755. "ContinuationToken": null
  1756. }))
  1757. }
  1758. async fn _revoke_organization_user(
  1759. org_id: &str,
  1760. org_user_id: &str,
  1761. headers: &AdminHeaders,
  1762. conn: &mut DbConn,
  1763. ) -> EmptyResult {
  1764. match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
  1765. Some(mut user_org) if user_org.status > UserOrgStatus::Revoked as i32 => {
  1766. if user_org.user_uuid == headers.user.uuid {
  1767. err!("You cannot revoke yourself")
  1768. }
  1769. if user_org.atype == UserOrgType::Owner && headers.org_user_type != UserOrgType::Owner {
  1770. err!("Only owners can revoke other owners")
  1771. }
  1772. if user_org.atype == UserOrgType::Owner
  1773. && UserOrganization::count_confirmed_by_org_and_type(org_id, UserOrgType::Owner, conn).await <= 1
  1774. {
  1775. err!("Organization must have at least one confirmed owner")
  1776. }
  1777. user_org.revoke();
  1778. user_org.save(conn).await?;
  1779. log_event(
  1780. EventType::OrganizationUserRevoked as i32,
  1781. &user_org.uuid,
  1782. org_id,
  1783. headers.user.uuid.clone(),
  1784. headers.device.atype,
  1785. &headers.ip.ip,
  1786. conn,
  1787. )
  1788. .await;
  1789. }
  1790. Some(_) => err!("User is already revoked"),
  1791. None => err!("User not found in organization"),
  1792. }
  1793. Ok(())
  1794. }
  1795. // Pre web-vault v2022.9.x endpoint
  1796. #[put("/organizations/<org_id>/users/<org_user_id>/activate")]
  1797. async fn activate_organization_user(
  1798. org_id: &str,
  1799. org_user_id: &str,
  1800. headers: AdminHeaders,
  1801. mut conn: DbConn,
  1802. ) -> EmptyResult {
  1803. _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await
  1804. }
  1805. // Pre web-vault v2022.9.x endpoint
  1806. #[put("/organizations/<org_id>/users/activate", data = "<data>")]
  1807. async fn bulk_activate_organization_user(
  1808. org_id: &str,
  1809. data: JsonUpcase<Value>,
  1810. headers: AdminHeaders,
  1811. conn: DbConn,
  1812. ) -> Json<Value> {
  1813. bulk_restore_organization_user(org_id, data, headers, conn).await
  1814. }
  1815. #[put("/organizations/<org_id>/users/<org_user_id>/restore")]
  1816. async fn restore_organization_user(
  1817. org_id: &str,
  1818. org_user_id: &str,
  1819. headers: AdminHeaders,
  1820. mut conn: DbConn,
  1821. ) -> EmptyResult {
  1822. _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await
  1823. }
  1824. #[put("/organizations/<org_id>/users/restore", data = "<data>")]
  1825. async fn bulk_restore_organization_user(
  1826. org_id: &str,
  1827. data: JsonUpcase<Value>,
  1828. headers: AdminHeaders,
  1829. mut conn: DbConn,
  1830. ) -> Json<Value> {
  1831. let data = data.into_inner().data;
  1832. let mut bulk_response = Vec::new();
  1833. match data["Ids"].as_array() {
  1834. Some(org_users) => {
  1835. for org_user_id in org_users {
  1836. let org_user_id = org_user_id.as_str().unwrap_or_default();
  1837. let err_msg = match _restore_organization_user(org_id, org_user_id, &headers, &mut conn).await {
  1838. Ok(_) => String::new(),
  1839. Err(e) => format!("{e:?}"),
  1840. };
  1841. bulk_response.push(json!(
  1842. {
  1843. "Object": "OrganizationUserBulkResponseModel",
  1844. "Id": org_user_id,
  1845. "Error": err_msg
  1846. }
  1847. ));
  1848. }
  1849. }
  1850. None => error!("No users to restore"),
  1851. }
  1852. Json(json!({
  1853. "Data": bulk_response,
  1854. "Object": "list",
  1855. "ContinuationToken": null
  1856. }))
  1857. }
  1858. async fn _restore_organization_user(
  1859. org_id: &str,
  1860. org_user_id: &str,
  1861. headers: &AdminHeaders,
  1862. conn: &mut DbConn,
  1863. ) -> EmptyResult {
  1864. match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
  1865. Some(mut user_org) if user_org.status < UserOrgStatus::Accepted as i32 => {
  1866. if user_org.user_uuid == headers.user.uuid {
  1867. err!("You cannot restore yourself")
  1868. }
  1869. if user_org.atype == UserOrgType::Owner && headers.org_user_type != UserOrgType::Owner {
  1870. err!("Only owners can restore other owners")
  1871. }
  1872. // This check is also done at accept_invite(), _confirm_invite, _activate_user(), edit_user(), admin::update_user_org_type
  1873. // It returns different error messages per function.
  1874. if user_org.atype < UserOrgType::Admin {
  1875. match OrgPolicy::is_user_allowed(&user_org.user_uuid, org_id, false, conn).await {
  1876. Ok(_) => {}
  1877. Err(OrgPolicyErr::TwoFactorMissing) => {
  1878. err!("You cannot restore this user because it has no two-step login method activated");
  1879. }
  1880. Err(OrgPolicyErr::SingleOrgEnforced) => {
  1881. err!("You cannot restore this user because it is a member of an organization which forbids it");
  1882. }
  1883. }
  1884. }
  1885. user_org.restore();
  1886. user_org.save(conn).await?;
  1887. log_event(
  1888. EventType::OrganizationUserRestored as i32,
  1889. &user_org.uuid,
  1890. org_id,
  1891. headers.user.uuid.clone(),
  1892. headers.device.atype,
  1893. &headers.ip.ip,
  1894. conn,
  1895. )
  1896. .await;
  1897. }
  1898. Some(_) => err!("User is already active"),
  1899. None => err!("User not found in organization"),
  1900. }
  1901. Ok(())
  1902. }
  1903. #[get("/organizations/<org_id>/groups")]
  1904. async fn get_groups(org_id: &str, _headers: ManagerHeadersLoose, mut conn: DbConn) -> JsonResult {
  1905. let groups: Vec<Value> = if CONFIG.org_groups_enabled() {
  1906. // Group::find_by_organization(&org_id, &mut conn).await.iter().map(Group::to_json).collect::<Value>()
  1907. let groups = Group::find_by_organization(org_id, &mut conn).await;
  1908. let mut groups_json = Vec::with_capacity(groups.len());
  1909. for g in groups {
  1910. groups_json.push(g.to_json_details(&mut conn).await)
  1911. }
  1912. groups_json
  1913. } else {
  1914. // The Bitwarden clients seem to call this API regardless of whether groups are enabled,
  1915. // so just act as if there are no groups.
  1916. Vec::with_capacity(0)
  1917. };
  1918. Ok(Json(json!({
  1919. "Data": groups,
  1920. "Object": "list",
  1921. "ContinuationToken": null,
  1922. })))
  1923. }
  1924. #[derive(Deserialize)]
  1925. #[allow(non_snake_case)]
  1926. struct GroupRequest {
  1927. Name: String,
  1928. AccessAll: Option<bool>,
  1929. ExternalId: Option<String>,
  1930. Collections: Vec<SelectionReadOnly>,
  1931. Users: Vec<String>,
  1932. }
  1933. impl GroupRequest {
  1934. pub fn to_group(&self, organizations_uuid: &str) -> ApiResult<Group> {
  1935. match self.AccessAll {
  1936. Some(access_all_value) => Ok(Group::new(
  1937. organizations_uuid.to_owned(),
  1938. self.Name.clone(),
  1939. access_all_value,
  1940. self.ExternalId.clone(),
  1941. )),
  1942. _ => err!("Could not convert GroupRequest to Group, because AccessAll has no value!"),
  1943. }
  1944. }
  1945. pub fn update_group(&self, mut group: Group) -> ApiResult<Group> {
  1946. match self.AccessAll {
  1947. Some(access_all_value) => {
  1948. group.name = self.Name.clone();
  1949. group.access_all = access_all_value;
  1950. group.set_external_id(self.ExternalId.clone());
  1951. Ok(group)
  1952. }
  1953. _ => err!("Could not update group, because AccessAll has no value!"),
  1954. }
  1955. }
  1956. }
  1957. #[derive(Deserialize, Serialize)]
  1958. #[allow(non_snake_case)]
  1959. struct SelectionReadOnly {
  1960. Id: String,
  1961. ReadOnly: bool,
  1962. HidePasswords: bool,
  1963. }
  1964. impl SelectionReadOnly {
  1965. pub fn to_collection_group(&self, groups_uuid: String) -> CollectionGroup {
  1966. CollectionGroup::new(self.Id.clone(), groups_uuid, self.ReadOnly, self.HidePasswords)
  1967. }
  1968. pub fn to_collection_group_details_read_only(collection_group: &CollectionGroup) -> SelectionReadOnly {
  1969. SelectionReadOnly {
  1970. Id: collection_group.groups_uuid.clone(),
  1971. ReadOnly: collection_group.read_only,
  1972. HidePasswords: collection_group.hide_passwords,
  1973. }
  1974. }
  1975. pub fn to_collection_user_details_read_only(collection_user: &CollectionUser) -> SelectionReadOnly {
  1976. SelectionReadOnly {
  1977. Id: collection_user.user_uuid.clone(),
  1978. ReadOnly: collection_user.read_only,
  1979. HidePasswords: collection_user.hide_passwords,
  1980. }
  1981. }
  1982. pub fn to_json(&self) -> Value {
  1983. json!(self)
  1984. }
  1985. }
  1986. #[post("/organizations/<org_id>/groups/<group_id>", data = "<data>")]
  1987. async fn post_group(
  1988. org_id: &str,
  1989. group_id: &str,
  1990. data: JsonUpcase<GroupRequest>,
  1991. headers: AdminHeaders,
  1992. conn: DbConn,
  1993. ) -> JsonResult {
  1994. put_group(org_id, group_id, data, headers, conn).await
  1995. }
  1996. #[post("/organizations/<org_id>/groups", data = "<data>")]
  1997. async fn post_groups(
  1998. org_id: &str,
  1999. headers: AdminHeaders,
  2000. data: JsonUpcase<GroupRequest>,
  2001. mut conn: DbConn,
  2002. ) -> JsonResult {
  2003. if !CONFIG.org_groups_enabled() {
  2004. err!("Group support is disabled");
  2005. }
  2006. let group_request = data.into_inner().data;
  2007. let group = group_request.to_group(org_id)?;
  2008. log_event(
  2009. EventType::GroupCreated as i32,
  2010. &group.uuid,
  2011. org_id,
  2012. headers.user.uuid.clone(),
  2013. headers.device.atype,
  2014. &headers.ip.ip,
  2015. &mut conn,
  2016. )
  2017. .await;
  2018. add_update_group(group, group_request.Collections, group_request.Users, org_id, &headers, &mut conn).await
  2019. }
  2020. #[put("/organizations/<org_id>/groups/<group_id>", data = "<data>")]
  2021. async fn put_group(
  2022. org_id: &str,
  2023. group_id: &str,
  2024. data: JsonUpcase<GroupRequest>,
  2025. headers: AdminHeaders,
  2026. mut conn: DbConn,
  2027. ) -> JsonResult {
  2028. if !CONFIG.org_groups_enabled() {
  2029. err!("Group support is disabled");
  2030. }
  2031. let group = match Group::find_by_uuid(group_id, &mut conn).await {
  2032. Some(group) => group,
  2033. None => err!("Group not found"),
  2034. };
  2035. let group_request = data.into_inner().data;
  2036. let updated_group = group_request.update_group(group)?;
  2037. CollectionGroup::delete_all_by_group(group_id, &mut conn).await?;
  2038. GroupUser::delete_all_by_group(group_id, &mut conn).await?;
  2039. log_event(
  2040. EventType::GroupUpdated as i32,
  2041. &updated_group.uuid,
  2042. org_id,
  2043. headers.user.uuid.clone(),
  2044. headers.device.atype,
  2045. &headers.ip.ip,
  2046. &mut conn,
  2047. )
  2048. .await;
  2049. add_update_group(updated_group, group_request.Collections, group_request.Users, org_id, &headers, &mut conn).await
  2050. }
  2051. async fn add_update_group(
  2052. mut group: Group,
  2053. collections: Vec<SelectionReadOnly>,
  2054. users: Vec<String>,
  2055. org_id: &str,
  2056. headers: &AdminHeaders,
  2057. conn: &mut DbConn,
  2058. ) -> JsonResult {
  2059. group.save(conn).await?;
  2060. for selection_read_only_request in collections {
  2061. let mut collection_group = selection_read_only_request.to_collection_group(group.uuid.clone());
  2062. collection_group.save(conn).await?;
  2063. }
  2064. for assigned_user_id in users {
  2065. let mut user_entry = GroupUser::new(group.uuid.clone(), assigned_user_id.clone());
  2066. user_entry.save(conn).await?;
  2067. log_event(
  2068. EventType::OrganizationUserUpdatedGroups as i32,
  2069. &assigned_user_id,
  2070. org_id,
  2071. headers.user.uuid.clone(),
  2072. headers.device.atype,
  2073. &headers.ip.ip,
  2074. conn,
  2075. )
  2076. .await;
  2077. }
  2078. Ok(Json(json!({
  2079. "Id": group.uuid,
  2080. "OrganizationId": group.organizations_uuid,
  2081. "Name": group.name,
  2082. "AccessAll": group.access_all,
  2083. "ExternalId": group.get_external_id()
  2084. })))
  2085. }
  2086. #[get("/organizations/<_org_id>/groups/<group_id>/details")]
  2087. async fn get_group_details(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
  2088. if !CONFIG.org_groups_enabled() {
  2089. err!("Group support is disabled");
  2090. }
  2091. let group = match Group::find_by_uuid(group_id, &mut conn).await {
  2092. Some(group) => group,
  2093. _ => err!("Group could not be found!"),
  2094. };
  2095. Ok(Json(group.to_json_details(&mut conn).await))
  2096. }
  2097. #[post("/organizations/<org_id>/groups/<group_id>/delete")]
  2098. async fn post_delete_group(org_id: &str, group_id: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
  2099. _delete_group(org_id, group_id, &headers, &mut conn).await
  2100. }
  2101. #[delete("/organizations/<org_id>/groups/<group_id>")]
  2102. async fn delete_group(org_id: &str, group_id: &str, headers: AdminHeaders, mut conn: DbConn) -> EmptyResult {
  2103. _delete_group(org_id, group_id, &headers, &mut conn).await
  2104. }
  2105. async fn _delete_group(org_id: &str, group_id: &str, headers: &AdminHeaders, conn: &mut DbConn) -> EmptyResult {
  2106. if !CONFIG.org_groups_enabled() {
  2107. err!("Group support is disabled");
  2108. }
  2109. let group = match Group::find_by_uuid(group_id, conn).await {
  2110. Some(group) => group,
  2111. _ => err!("Group not found"),
  2112. };
  2113. log_event(
  2114. EventType::GroupDeleted as i32,
  2115. &group.uuid,
  2116. org_id,
  2117. headers.user.uuid.clone(),
  2118. headers.device.atype,
  2119. &headers.ip.ip,
  2120. conn,
  2121. )
  2122. .await;
  2123. group.delete(conn).await
  2124. }
  2125. #[delete("/organizations/<org_id>/groups", data = "<data>")]
  2126. async fn bulk_delete_groups(
  2127. org_id: &str,
  2128. data: JsonUpcase<OrgBulkIds>,
  2129. headers: AdminHeaders,
  2130. mut conn: DbConn,
  2131. ) -> EmptyResult {
  2132. if !CONFIG.org_groups_enabled() {
  2133. err!("Group support is disabled");
  2134. }
  2135. let data: OrgBulkIds = data.into_inner().data;
  2136. for group_id in data.Ids {
  2137. _delete_group(org_id, &group_id, &headers, &mut conn).await?
  2138. }
  2139. Ok(())
  2140. }
  2141. #[get("/organizations/<_org_id>/groups/<group_id>")]
  2142. async fn get_group(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
  2143. if !CONFIG.org_groups_enabled() {
  2144. err!("Group support is disabled");
  2145. }
  2146. let group = match Group::find_by_uuid(group_id, &mut conn).await {
  2147. Some(group) => group,
  2148. _ => err!("Group not found"),
  2149. };
  2150. Ok(Json(group.to_json()))
  2151. }
  2152. #[get("/organizations/<_org_id>/groups/<group_id>/users")]
  2153. async fn get_group_users(_org_id: &str, group_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
  2154. if !CONFIG.org_groups_enabled() {
  2155. err!("Group support is disabled");
  2156. }
  2157. match Group::find_by_uuid(group_id, &mut conn).await {
  2158. Some(_) => { /* Do nothing */ }
  2159. _ => err!("Group could not be found!"),
  2160. };
  2161. let group_users: Vec<String> = GroupUser::find_by_group(group_id, &mut conn)
  2162. .await
  2163. .iter()
  2164. .map(|entry| entry.users_organizations_uuid.clone())
  2165. .collect();
  2166. Ok(Json(json!(group_users)))
  2167. }
  2168. #[put("/organizations/<org_id>/groups/<group_id>/users", data = "<data>")]
  2169. async fn put_group_users(
  2170. org_id: &str,
  2171. group_id: &str,
  2172. headers: AdminHeaders,
  2173. data: JsonVec<String>,
  2174. mut conn: DbConn,
  2175. ) -> EmptyResult {
  2176. if !CONFIG.org_groups_enabled() {
  2177. err!("Group support is disabled");
  2178. }
  2179. match Group::find_by_uuid(group_id, &mut conn).await {
  2180. Some(_) => { /* Do nothing */ }
  2181. _ => err!("Group could not be found!"),
  2182. };
  2183. GroupUser::delete_all_by_group(group_id, &mut conn).await?;
  2184. let assigned_user_ids = data.into_inner();
  2185. for assigned_user_id in assigned_user_ids {
  2186. let mut user_entry = GroupUser::new(String::from(group_id), assigned_user_id.clone());
  2187. user_entry.save(&mut conn).await?;
  2188. log_event(
  2189. EventType::OrganizationUserUpdatedGroups as i32,
  2190. &assigned_user_id,
  2191. org_id,
  2192. headers.user.uuid.clone(),
  2193. headers.device.atype,
  2194. &headers.ip.ip,
  2195. &mut conn,
  2196. )
  2197. .await;
  2198. }
  2199. Ok(())
  2200. }
  2201. #[get("/organizations/<_org_id>/users/<user_id>/groups")]
  2202. async fn get_user_groups(_org_id: &str, user_id: &str, _headers: AdminHeaders, mut conn: DbConn) -> JsonResult {
  2203. if !CONFIG.org_groups_enabled() {
  2204. err!("Group support is disabled");
  2205. }
  2206. match UserOrganization::find_by_uuid(user_id, &mut conn).await {
  2207. Some(_) => { /* Do nothing */ }
  2208. _ => err!("User could not be found!"),
  2209. };
  2210. let user_groups: Vec<String> =
  2211. GroupUser::find_by_user(user_id, &mut conn).await.iter().map(|entry| entry.groups_uuid.clone()).collect();
  2212. Ok(Json(json!(user_groups)))
  2213. }
  2214. #[derive(Deserialize)]
  2215. #[allow(non_snake_case)]
  2216. struct OrganizationUserUpdateGroupsRequest {
  2217. GroupIds: Vec<String>,
  2218. }
  2219. #[post("/organizations/<org_id>/users/<org_user_id>/groups", data = "<data>")]
  2220. async fn post_user_groups(
  2221. org_id: &str,
  2222. org_user_id: &str,
  2223. data: JsonUpcase<OrganizationUserUpdateGroupsRequest>,
  2224. headers: AdminHeaders,
  2225. conn: DbConn,
  2226. ) -> EmptyResult {
  2227. put_user_groups(org_id, org_user_id, data, headers, conn).await
  2228. }
  2229. #[put("/organizations/<org_id>/users/<org_user_id>/groups", data = "<data>")]
  2230. async fn put_user_groups(
  2231. org_id: &str,
  2232. org_user_id: &str,
  2233. data: JsonUpcase<OrganizationUserUpdateGroupsRequest>,
  2234. headers: AdminHeaders,
  2235. mut conn: DbConn,
  2236. ) -> EmptyResult {
  2237. if !CONFIG.org_groups_enabled() {
  2238. err!("Group support is disabled");
  2239. }
  2240. match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
  2241. Some(_) => { /* Do nothing */ }
  2242. _ => err!("User could not be found!"),
  2243. };
  2244. GroupUser::delete_all_by_user(org_user_id, &mut conn).await?;
  2245. let assigned_group_ids = data.into_inner().data;
  2246. for assigned_group_id in assigned_group_ids.GroupIds {
  2247. let mut group_user = GroupUser::new(assigned_group_id.clone(), String::from(org_user_id));
  2248. group_user.save(&mut conn).await?;
  2249. }
  2250. log_event(
  2251. EventType::OrganizationUserUpdatedGroups as i32,
  2252. org_user_id,
  2253. org_id,
  2254. headers.user.uuid.clone(),
  2255. headers.device.atype,
  2256. &headers.ip.ip,
  2257. &mut conn,
  2258. )
  2259. .await;
  2260. Ok(())
  2261. }
  2262. #[post("/organizations/<org_id>/groups/<group_id>/delete-user/<org_user_id>")]
  2263. async fn post_delete_group_user(
  2264. org_id: &str,
  2265. group_id: &str,
  2266. org_user_id: &str,
  2267. headers: AdminHeaders,
  2268. conn: DbConn,
  2269. ) -> EmptyResult {
  2270. delete_group_user(org_id, group_id, org_user_id, headers, conn).await
  2271. }
  2272. #[delete("/organizations/<org_id>/groups/<group_id>/users/<org_user_id>")]
  2273. async fn delete_group_user(
  2274. org_id: &str,
  2275. group_id: &str,
  2276. org_user_id: &str,
  2277. headers: AdminHeaders,
  2278. mut conn: DbConn,
  2279. ) -> EmptyResult {
  2280. if !CONFIG.org_groups_enabled() {
  2281. err!("Group support is disabled");
  2282. }
  2283. match UserOrganization::find_by_uuid(org_user_id, &mut conn).await {
  2284. Some(_) => { /* Do nothing */ }
  2285. _ => err!("User could not be found!"),
  2286. };
  2287. match Group::find_by_uuid(group_id, &mut conn).await {
  2288. Some(_) => { /* Do nothing */ }
  2289. _ => err!("Group could not be found!"),
  2290. };
  2291. log_event(
  2292. EventType::OrganizationUserUpdatedGroups as i32,
  2293. org_user_id,
  2294. org_id,
  2295. headers.user.uuid.clone(),
  2296. headers.device.atype,
  2297. &headers.ip.ip,
  2298. &mut conn,
  2299. )
  2300. .await;
  2301. GroupUser::delete_by_group_id_and_user_id(group_id, org_user_id, &mut conn).await
  2302. }
  2303. #[derive(Deserialize)]
  2304. #[allow(non_snake_case)]
  2305. struct OrganizationUserResetPasswordEnrollmentRequest {
  2306. ResetPasswordKey: Option<String>,
  2307. }
  2308. #[derive(Deserialize)]
  2309. #[allow(non_snake_case)]
  2310. struct OrganizationUserResetPasswordRequest {
  2311. NewMasterPasswordHash: String,
  2312. Key: String,
  2313. }
  2314. #[get("/organizations/<org_id>/keys")]
  2315. async fn get_organization_keys(org_id: &str, mut conn: DbConn) -> JsonResult {
  2316. let org = match Organization::find_by_uuid(org_id, &mut conn).await {
  2317. Some(organization) => organization,
  2318. None => err!("Organization not found"),
  2319. };
  2320. Ok(Json(json!({
  2321. "Object": "organizationKeys",
  2322. "PublicKey": org.public_key,
  2323. "PrivateKey": org.private_key,
  2324. })))
  2325. }
  2326. #[put("/organizations/<org_id>/users/<org_user_id>/reset-password", data = "<data>")]
  2327. async fn put_reset_password(
  2328. org_id: &str,
  2329. org_user_id: &str,
  2330. headers: AdminHeaders,
  2331. data: JsonUpcase<OrganizationUserResetPasswordRequest>,
  2332. mut conn: DbConn,
  2333. nt: Notify<'_>,
  2334. ) -> EmptyResult {
  2335. let org = match Organization::find_by_uuid(org_id, &mut conn).await {
  2336. Some(org) => org,
  2337. None => err!("Required organization not found"),
  2338. };
  2339. let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, &org.uuid, &mut conn).await {
  2340. Some(user) => user,
  2341. None => err!("User to reset isn't member of required organization"),
  2342. };
  2343. let user = match User::find_by_uuid(&org_user.user_uuid, &mut conn).await {
  2344. Some(user) => user,
  2345. None => err!("User not found"),
  2346. };
  2347. check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?;
  2348. if org_user.reset_password_key.is_none() {
  2349. err!("Password reset not or not correctly enrolled");
  2350. }
  2351. if org_user.status != (UserOrgStatus::Confirmed as i32) {
  2352. err!("Organization user must be confirmed for password reset functionality");
  2353. }
  2354. // Sending email before resetting password to ensure working email configuration and the resulting
  2355. // user notification. Also this might add some protection against security flaws and misuse
  2356. if let Err(e) = mail::send_admin_reset_password(&user.email, &user.name, &org.name).await {
  2357. err!(format!("Error sending user reset password email: {e:#?}"));
  2358. }
  2359. let reset_request = data.into_inner().data;
  2360. let mut user = user;
  2361. user.set_password(reset_request.NewMasterPasswordHash.as_str(), Some(reset_request.Key), true, None);
  2362. user.save(&mut conn).await?;
  2363. nt.send_logout(&user, None, &mut conn).await;
  2364. log_event(
  2365. EventType::OrganizationUserAdminResetPassword as i32,
  2366. org_user_id,
  2367. org_id,
  2368. headers.user.uuid.clone(),
  2369. headers.device.atype,
  2370. &headers.ip.ip,
  2371. &mut conn,
  2372. )
  2373. .await;
  2374. Ok(())
  2375. }
  2376. #[get("/organizations/<org_id>/users/<org_user_id>/reset-password-details")]
  2377. async fn get_reset_password_details(
  2378. org_id: &str,
  2379. org_user_id: &str,
  2380. headers: AdminHeaders,
  2381. mut conn: DbConn,
  2382. ) -> JsonResult {
  2383. let org = match Organization::find_by_uuid(org_id, &mut conn).await {
  2384. Some(org) => org,
  2385. None => err!("Required organization not found"),
  2386. };
  2387. let org_user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, &mut conn).await {
  2388. Some(user) => user,
  2389. None => err!("User to reset isn't member of required organization"),
  2390. };
  2391. let user = match User::find_by_uuid(&org_user.user_uuid, &mut conn).await {
  2392. Some(user) => user,
  2393. None => err!("User not found"),
  2394. };
  2395. check_reset_password_applicable_and_permissions(org_id, org_user_id, &headers, &mut conn).await?;
  2396. // https://github.com/bitwarden/server/blob/3b50ccb9f804efaacdc46bed5b60e5b28eddefcf/src/Api/Models/Response/Organizations/OrganizationUserResponseModel.cs#L111
  2397. Ok(Json(json!({
  2398. "Object": "organizationUserResetPasswordDetails",
  2399. "Kdf":user.client_kdf_type,
  2400. "KdfIterations":user.client_kdf_iter,
  2401. "KdfMemory":user.client_kdf_memory,
  2402. "KdfParallelism":user.client_kdf_parallelism,
  2403. "ResetPasswordKey":org_user.reset_password_key,
  2404. "EncryptedPrivateKey":org.private_key,
  2405. })))
  2406. }
  2407. async fn check_reset_password_applicable_and_permissions(
  2408. org_id: &str,
  2409. org_user_id: &str,
  2410. headers: &AdminHeaders,
  2411. conn: &mut DbConn,
  2412. ) -> EmptyResult {
  2413. check_reset_password_applicable(org_id, conn).await?;
  2414. let target_user = match UserOrganization::find_by_uuid_and_org(org_user_id, org_id, conn).await {
  2415. Some(user) => user,
  2416. None => err!("Reset target user not found"),
  2417. };
  2418. // Resetting user must be higher/equal to user to reset
  2419. match headers.org_user_type {
  2420. UserOrgType::Owner => Ok(()),
  2421. UserOrgType::Admin if target_user.atype <= UserOrgType::Admin => Ok(()),
  2422. _ => err!("No permission to reset this user's password"),
  2423. }
  2424. }
  2425. async fn check_reset_password_applicable(org_id: &str, conn: &mut DbConn) -> EmptyResult {
  2426. if !CONFIG.mail_enabled() {
  2427. err!("Password reset is not supported on an email-disabled instance.");
  2428. }
  2429. let policy = match OrgPolicy::find_by_org_and_type(org_id, OrgPolicyType::ResetPassword, conn).await {
  2430. Some(p) => p,
  2431. None => err!("Policy not found"),
  2432. };
  2433. if !policy.enabled {
  2434. err!("Reset password policy not enabled");
  2435. }
  2436. Ok(())
  2437. }
  2438. #[put("/organizations/<org_id>/users/<org_user_id>/reset-password-enrollment", data = "<data>")]
  2439. async fn put_reset_password_enrollment(
  2440. org_id: &str,
  2441. org_user_id: &str,
  2442. headers: Headers,
  2443. data: JsonUpcase<OrganizationUserResetPasswordEnrollmentRequest>,
  2444. mut conn: DbConn,
  2445. ) -> EmptyResult {
  2446. let mut org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, org_id, &mut conn).await {
  2447. Some(u) => u,
  2448. None => err!("User to enroll isn't member of required organization"),
  2449. };
  2450. check_reset_password_applicable(org_id, &mut conn).await?;
  2451. let reset_request = data.into_inner().data;
  2452. if reset_request.ResetPasswordKey.is_none() && OrgPolicy::org_is_reset_password_auto_enroll(org_id, &mut conn).await
  2453. {
  2454. err!("Reset password can't be withdrawed due to an enterprise policy");
  2455. }
  2456. org_user.reset_password_key = reset_request.ResetPasswordKey;
  2457. org_user.save(&mut conn).await?;
  2458. let log_id = if org_user.reset_password_key.is_some() {
  2459. EventType::OrganizationUserResetPasswordEnroll as i32
  2460. } else {
  2461. EventType::OrganizationUserResetPasswordWithdraw as i32
  2462. };
  2463. log_event(log_id, org_user_id, org_id, headers.user.uuid.clone(), headers.device.atype, &headers.ip.ip, &mut conn)
  2464. .await;
  2465. Ok(())
  2466. }
  2467. // This is a new function active since the v2022.9.x clients.
  2468. // It combines the previous two calls done before.
  2469. // We call those two functions here and combine them our selfs.
  2470. //
  2471. // NOTE: It seems clients can't handle uppercase-first keys!!
  2472. // We need to convert all keys so they have the first character to be a lowercase.
  2473. // Else the export will be just an empty JSON file.
  2474. #[get("/organizations/<org_id>/export")]
  2475. async fn get_org_export(org_id: &str, headers: AdminHeaders, mut conn: DbConn) -> Json<Value> {
  2476. use semver::{Version, VersionReq};
  2477. // Since version v2023.1.0 the format of the export is different.
  2478. // Also, this endpoint was created since v2022.9.0.
  2479. // Therefore, we will check for any version smaller then v2023.1.0 and return a different response.
  2480. // If we can't determine the version, we will use the latest default v2023.1.0 and higher.
  2481. // https://github.com/bitwarden/server/blob/9ca93381ce416454734418c3a9f99ab49747f1b6/src/Api/Controllers/OrganizationExportController.cs#L44
  2482. let use_list_response_model = if let Some(client_version) = headers.client_version {
  2483. let ver_match = VersionReq::parse("<2023.1.0").unwrap();
  2484. let client_version = Version::parse(&client_version).unwrap();
  2485. ver_match.matches(&client_version)
  2486. } else {
  2487. false
  2488. };
  2489. // Also both main keys here need to be lowercase, else the export will fail.
  2490. if use_list_response_model {
  2491. // Backwards compatible pre v2023.1.0 response
  2492. Json(json!({
  2493. "collections": {
  2494. "data": convert_json_key_lcase_first(_get_org_collections(org_id, &mut conn).await),
  2495. "object": "list",
  2496. "continuationToken": null,
  2497. },
  2498. "ciphers": {
  2499. "data": convert_json_key_lcase_first(_get_org_details(org_id, &headers.host, &headers.user.uuid, &mut conn).await),
  2500. "object": "list",
  2501. "continuationToken": null,
  2502. }
  2503. }))
  2504. } else {
  2505. // v2023.1.0 and newer response
  2506. Json(json!({
  2507. "collections": convert_json_key_lcase_first(_get_org_collections(org_id, &mut conn).await),
  2508. "ciphers": convert_json_key_lcase_first(_get_org_details(org_id, &headers.host, &headers.user.uuid, &mut conn).await),
  2509. }))
  2510. }
  2511. }