SiteApi.hx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package tools.haxelib;
  2. import tools.haxelib.Datas;
  3. import tools.haxelib.SiteDb;
  4. class SiteApi {
  5. var db : neko.db.Connection;
  6. public function new( db ) {
  7. this.db = db;
  8. }
  9. public function search( word : String ) : List<{ id : Int, name : String }> {
  10. return Project.manager.containing(word);
  11. }
  12. public function infos( project : String ) : ProjectInfos {
  13. var p = Project.manager.search({ name : project }).first();
  14. if( p == null )
  15. throw "No such Project : "+project;
  16. var vl = Version.manager.search({ project : p.id });
  17. var versions = new Array();
  18. for( v in vl )
  19. versions.push({ name : v.name, comments : v.comments, date : v.date });
  20. return {
  21. name : p.name,
  22. curversion : if( p.version == null ) null else p.version.name,
  23. desc : p.description,
  24. versions : versions,
  25. owner : p.owner.name,
  26. website : p.website,
  27. license : p.license,
  28. tags : Tag.manager.search({ project : p.id }).map(function(t) return t.tag),
  29. };
  30. }
  31. public function user( name : String ) : UserInfos {
  32. var u = User.manager.search({ name : name }).first();
  33. if( u == null )
  34. throw "No such user : "+name;
  35. var pl = Project.manager.search({ owner : u.id });
  36. var projects = new Array();
  37. for( p in pl )
  38. projects.push(p.name);
  39. return {
  40. name : u.name,
  41. fullname : u.fullname,
  42. email : u.email,
  43. projects : projects,
  44. };
  45. }
  46. public function register( name : String, pass : String, mail : String, fullname : String ) : Bool {
  47. if( !Datas.alphanum.match(name) )
  48. throw "Invalid user name, please use alphanumeric characters";
  49. if( name.length < 3 )
  50. throw "User name must be at least 3 characters";
  51. var u = new User();
  52. u.name = name;
  53. u.pass = pass;
  54. u.email = mail;
  55. u.fullname = fullname;
  56. u.insert();
  57. return null;
  58. }
  59. public function isNewUser( name : String ) : Bool {
  60. return User.manager.search({ name : name }).first() == null;
  61. }
  62. public function checkDeveloper( prj : String, user : String ) : Void {
  63. var p = Project.manager.search({ name : prj }).first();
  64. if( p == null )
  65. return;
  66. for( d in Developer.manager.search({ project : p.id }) )
  67. if( d.user.name == user )
  68. return;
  69. throw "User '"+user+"' is not a developer of project '"+prj+"'";
  70. }
  71. public function checkPassword( user : String, pass : String ) : Bool {
  72. var u = User.manager.search({ name : user }).first();
  73. return u != null && u.pass == pass;
  74. }
  75. public function getSubmitId() : String {
  76. return Std.string(Std.random(100000000));
  77. }
  78. public function processSubmit( id : String, user : String, pass : String ) : String {
  79. var path = Site.TMP_DIR+"/"+Std.parseInt(id)+".tmp";
  80. var file = try neko.io.File.read(path,true) catch( e : Dynamic ) throw "Invalid file id #"+id;
  81. var zip = try neko.zip.Reader.readZip(file) catch( e : Dynamic ) { file.close(); neko.Lib.rethrow(e); };
  82. file.close();
  83. var infos = Datas.readInfos(zip,true);
  84. var u = User.manager.search({ name : user }).first();
  85. if( u == null || u.pass != pass )
  86. throw "Invalid username or password";
  87. var devs = infos.developers.map(function(user) {
  88. var u = User.manager.search({ name : user }).first();
  89. if( u == null )
  90. throw "Unknown user '"+user+"'";
  91. return u;
  92. });
  93. var tags = Lambda.array(infos.tags);
  94. tags.sort(Reflect.compare);
  95. var p = Project.manager.search({ name : infos.project }).first();
  96. // create project if needed
  97. if( p == null ) {
  98. p = new Project();
  99. p.name = infos.project;
  100. p.description = infos.desc;
  101. p.website = infos.website;
  102. p.license = infos.license;
  103. p.owner = u;
  104. p.insert();
  105. for( u in devs ) {
  106. var d = new Developer();
  107. d.user = u;
  108. d.project = p;
  109. d.insert();
  110. }
  111. for( tag in tags ) {
  112. var t = new Tag();
  113. t.tag = tag;
  114. t.project = p;
  115. t.insert();
  116. }
  117. }
  118. // check submit rights
  119. var pdevs = Developer.manager.search({ project : p.id });
  120. var isdev = false;
  121. for( d in pdevs )
  122. if( d.user.id == u.id ) {
  123. isdev = true;
  124. break;
  125. }
  126. if( !isdev )
  127. throw "You are not a developer of this project";
  128. var otags = Tag.manager.search({ project : p.id });
  129. var curtags = otags.map(function(t) return t.tag).join(":");
  130. // update public infos
  131. if( infos.desc != p.description || p.website != infos.website || p.license != infos.license || pdevs.length != devs.length || tags.join(":") != curtags ) {
  132. if( u.id != p.owner.id )
  133. throw "Only project owner can modify project infos";
  134. p.description = infos.desc;
  135. p.website = infos.website;
  136. p.license = infos.license;
  137. p.update();
  138. if( pdevs.length != devs.length ) {
  139. for( d in pdevs )
  140. d.delete();
  141. for( u in devs ) {
  142. var d = new Developer();
  143. d.user = u;
  144. d.project = p;
  145. d.insert();
  146. }
  147. }
  148. if( tags.join(":") != curtags ) {
  149. for( t in otags )
  150. t.delete();
  151. for( tag in tags ) {
  152. var t = new Tag();
  153. t.tag = tag;
  154. t.project = p;
  155. t.insert();
  156. }
  157. }
  158. }
  159. // look for current version
  160. var current = null;
  161. for( v in Version.manager.search({ project : p.id }) )
  162. if( v.name == infos.version ) {
  163. current = v;
  164. break;
  165. }
  166. // update documentation
  167. var doc = null;
  168. var docXML = Datas.readDoc(zip);
  169. if( docXML != null ) {
  170. var p = new haxe.rtti.XmlParser();
  171. p.process(Xml.parse(docXML).firstElement(),null);
  172. p.sort();
  173. var roots = new Array();
  174. for( x in p.root )
  175. switch( x ) {
  176. case TPackage(name,_,_):
  177. switch( name ) {
  178. case "flash","flash9","haxe","js","neko","cpp","php","tools": // don't include haXe core types
  179. default: roots.push(x);
  180. }
  181. default:
  182. // don't include haXe root types
  183. }
  184. var s = new haxe.Serializer();
  185. s.useEnumIndex = true;
  186. s.useCache = true;
  187. s.serialize(roots);
  188. doc = s.toString();
  189. }
  190. // update file
  191. var target = Site.REP_DIR+"/"+Datas.fileName(p.name,infos.version);
  192. if( current != null ) neko.FileSystem.deleteFile(target);
  193. neko.FileSystem.rename(path,target);
  194. // update existing version
  195. if( current != null ) {
  196. current.documentation = doc;
  197. current.comments = infos.versionComments;
  198. current.update();
  199. return "Version "+current.name+" (id#"+current.id+") updated";
  200. }
  201. // add new version
  202. var v = new Version();
  203. v.project = p;
  204. v.name = infos.version;
  205. v.comments = infos.versionComments;
  206. v.downloads = 0;
  207. v.date = Date.now().toString();
  208. v.documentation = doc;
  209. v.insert();
  210. p.version = v;
  211. p.update();
  212. return "Version "+v.name+" (id#"+v.id+") added";
  213. }
  214. public function postInstall( project : String, version : String ) {
  215. var p = Project.manager.search({ name : project }).first();
  216. if( p == null )
  217. throw "No such Project : "+project;
  218. var v = Version.manager.search({ project : p.id, name : version }).first();
  219. if( v == null )
  220. throw "No such Version : "+version;
  221. v.downloads++;
  222. v.update();
  223. p.downloads++;
  224. p.update();
  225. }
  226. }