Mercurial > hg > ChinaGisRestApi
comparison RestDbGisApi.py @ 61:e81d034b28a5
more permission handling and table metadata
author | casties |
---|---|
date | Tue, 26 Oct 2010 21:23:19 +0200 |
parents | 9fdadb60529f |
children | 3905385c8854 |
comparison
equal
deleted
inserted
replaced
60:9fdadb60529f | 61:e81d034b28a5 |
---|---|
7 from OFS.Folder import Folder | 7 from OFS.Folder import Folder |
8 from Products.PageTemplates.PageTemplateFile import PageTemplateFile | 8 from Products.PageTemplates.PageTemplateFile import PageTemplateFile |
9 from Products.ZSQLExtend import ZSQLExtend | 9 from Products.ZSQLExtend import ZSQLExtend |
10 import logging | 10 import logging |
11 import re | 11 import re |
12 import json | |
13 import time | 12 import time |
13 import datetime | |
14 import urllib | 14 import urllib |
15 | 15 |
16 from RestDbInterface import * | 16 from RestDbInterface import * |
17 | 17 |
18 | 18 |
44 meta_type="RESTgis" | 44 meta_type="RESTgis" |
45 | 45 |
46 # data templates | 46 # data templates |
47 GIS_schema_table = PageTemplateFile('zpt/GIS_schema_table', globals()) | 47 GIS_schema_table = PageTemplateFile('zpt/GIS_schema_table', globals()) |
48 KML_schema_table = PageTemplateFile('zpt/KML_schema_table', globals()) | 48 KML_schema_table = PageTemplateFile('zpt/KML_schema_table', globals()) |
49 HTML_schema_usertables = PageTemplateFile('zpt/HTML_schema_usertables', globals()) | |
49 | 50 |
50 # and scripts | 51 # and scripts |
51 def KML_URL_schema_table(self,schema,table): | 52 def KML_URL_schema_table(self,schema,table): |
52 """KML_URL table function""" | 53 """KML_URL table function""" |
53 self.REQUEST.RESPONSE.setHeader("Content-Type", "text/plain") | 54 self.REQUEST.RESPONSE.setHeader("Content-Type", "text/plain") |
54 id = self.REQUEST.get('id',[]) | 55 id = self.REQUEST.get('id',[]) |
55 doc = self.REQUEST.get('doc',None) | 56 doc = self.REQUEST.get('doc',None) |
56 return self.getLiveKmlUrl(schema=schema,table=table) | 57 return self.getLiveKmlUrl(schema=schema,table=table) |
57 | 58 |
58 | 59 # |
60 # database methods | |
61 # | |
59 def getTableOwner(self,schema,table): | 62 def getTableOwner(self,schema,table): |
60 """returns the owner of the table""" | 63 """returns the owner of the table""" |
61 # TODO: look up in metadata | 64 # what do we do with the schema? |
65 sql = 'select table_owner from public.gis_table_meta where table_name = %s' | |
66 res = self.executeSQL(sql,(table,)) | |
67 if len(res['rows']) > 0: | |
68 return res['rows'][0][0] | |
62 return None | 69 return None |
63 | 70 |
64 def isAllowed(self,action,schema,table,user=None,owner=None): | 71 def isAllowed(self,action,schema,table,user=None,owner=None): |
65 """returns if the requested action on the table is allowed""" | 72 """returns if the requested action on the table is allowed""" |
66 if user is None: | 73 if user is None: |
75 return False | 82 return False |
76 | 83 |
77 if action == "update": | 84 if action == "update": |
78 if owner is None: | 85 if owner is None: |
79 owner = self.getTableOwner(schema,table) | 86 owner = self.getTableOwner(schema,table) |
87 logging.debug("isAllowed user=%s owner=%s"%(user,owner)) | |
80 if user is not None and str(user) == str(owner): | 88 if user is not None and str(user) == str(owner): |
81 # update only your own table | 89 # update only your own table |
82 return True | 90 return True |
83 else: | 91 else: |
84 return False | 92 return False |
85 | 93 |
86 return True | 94 return True |
87 | 95 |
88 def setTableMetaTypes(self,schema,table,fields): | 96 def setTableMetaTypes(self,schema,table,fields,user=None): |
89 """sets the GIS meta information for table""" | 97 """sets the GIS meta information for table""" |
90 logging.debug("settablemetatypes schema=%s, table=%s, fields=%s"%(schema,table,fields)) | 98 if user is None: |
91 gisIdField = None | 99 user = self.REQUEST.get('AUTHENTICATED_USER',None) |
92 latField = None | 100 |
93 lonField = None | 101 logging.debug("settablemetatypes schema=%s, table=%s, fields=%s user=%s"%(schema,table,fields,user)) |
102 | |
103 today = datetime.date.today().isoformat() | |
104 | |
105 res = self.executeSQL('select * from public.gis_table_meta where table_name = %s', (table,)) | |
106 if len(res['rows']) > 0: | |
107 # meta record exists | |
108 sql = 'update public.gis_table_meta set table_owner=%s, table_modified=%s where table_name=%s' | |
109 self.executeSQL(sql, (str(user),today,table), hasResult=False) | |
110 else: | |
111 # new meta record | |
112 sql = 'insert into public.gis_table_meta (table_name,table_owner,table_created) values (%s,%s,%s)' | |
113 self.executeSQL(sql, (table,str(user),today), hasResult=False) | |
114 | |
115 # update row info | |
116 sql = 'delete from public.gis_table_meta_rows where table_name=%s' | |
117 self.executeSQL(sql,(table,),hasResult=False) | |
118 sql = 'insert into public.gis_table_meta_rows (table_name,field_name,gis_type) values (%s,%s,%s)' | |
94 for f in fields: | 119 for f in fields: |
95 t = f['type'] | 120 t = f['type'] |
96 if t == 'gis_id': | 121 fn = f['name'] |
97 gisIdField = f['name'] | 122 self.executeSQL(sql, (table,fn,t), hasResult=False) |
98 elif t == 'coord_lat': | |
99 latField = f['name'] | |
100 elif t == 'coord_lon': | |
101 lonField = f['name'] | |
102 | |
103 res = self.executeSQL("select * from public.metadata where tablename=%s", (table,)) | |
104 if len(res['rows']) > 0: | |
105 # meta record exists | |
106 if gisIdField is not None: | |
107 self.executeSQL('update public.metadata set "attribute with gis_id" = %s where tablename = %s', (gisIdField,table), hasResult=False) | |
108 | |
109 else: | |
110 # new meta record | |
111 if gisIdField is not None: | |
112 self.executeSQL('insert into public.metadata ("tablename", "attribute with gis_id") values (%s, %s)', (table,gisIdField), hasResult=False) | |
113 | |
114 | |
115 def showTable(self,resultFormat='XML',schema='public',table=None,REQUEST=None,RESPONSE=None): | |
116 """returns PageTemplate with tables""" | |
117 logging.debug("showtable") | |
118 if REQUEST is None: | |
119 REQUEST = self.REQUEST | |
120 | 123 |
121 # should be cross-site accessible | 124 |
122 if RESPONSE is None: | 125 def getListOfUserTables(self,schema='public',username='guest'): |
123 RESPONSE = self.REQUEST.RESPONSE | 126 """return list of tables""" |
124 RESPONSE.setHeader('Access-Control-Allow-Origin', '*') | 127 logging.debug("getlistofusertables") |
125 | 128 # get list of db tables |
126 user = self.REQUEST.get('AUTHENTICATED_USER',None) | 129 qstr = """SELECT t.table_name FROM information_schema.tables t, public.gis_table_meta m WHERE t.table_type = 'BASE TABLE' |
127 logging.debug("user=%s"%user) | 130 AND t.table_schema = %s AND t.table_name = m.table_name ORDER BY 1""" |
128 | 131 |
129 # everything else has its own template | 132 data=self.executeSQL(qstr,(schema,)) |
130 pt = getattr(self.template, '%s_schema_table'%resultFormat, None) | 133 return data |
131 if pt is None: | 134 |
132 return "ERROR!! template %s_schema_table not found"%resultFormat | |
133 | |
134 #data = self.getTable(schema,table) | |
135 # templates have to get their own data | |
136 return pt(schema=schema,table=table) | |
137 | |
138 | 135 |
139 def createEmptyTable(self,schema,table,fields): | 136 def createEmptyTable(self,schema,table,fields): |
140 """create a table with the given fields | 137 """create a table with the given fields |
141 returns list of created fields""" | 138 returns list of created fields""" |
142 logging.debug("createEmptyTable") | 139 sqlFields = RestDbInterface.createEmptyTable(self,schema,table,fields) |
143 sqlFields = [] | 140 if sqlFields is not None: |
144 for f in fields: | |
145 if isinstance(f,dict): | |
146 # {name: XX, type: YY} | |
147 name = sqlName(f['name']) | |
148 type = f['type'] | |
149 sqltype = gisToSqlTypeMap[type] | |
150 else: | |
151 # name only | |
152 name = sqlName(f) | |
153 type = 'text' | |
154 sqltype = 'text' | |
155 | |
156 sqlFields.append({'name':name, 'type':type, 'sqltype':sqltype}) | |
157 | |
158 if self.isAllowed("create", schema, table): | |
159 self.executeSQL('drop table if exists "%s"."%s"'%(schema,table),hasResult=False) | |
160 fieldString = ", ".join(['"%s" %s'%(f['name'],f['sqltype']) for f in sqlFields]) | |
161 sqlString = 'create table "%s"."%s" (%s)'%(schema,table,fieldString) | |
162 logging.debug("createemptytable: SQL=%s"%sqlString) | |
163 self.executeSQL(sqlString,hasResult=False) | |
164 self.setTableMetaTypes(schema,table,sqlFields) | 141 self.setTableMetaTypes(schema,table,sqlFields) |
165 return sqlFields | 142 |
166 else: | 143 return sqlFields |
167 logging.warning("create table not allowed!") | |
168 # throw exception? | |
169 return None | |
170 | 144 |
171 | 145 |
172 def getLiveKmlUrl(self,schema,table,useTimestamp=True,REQUEST=None): | 146 def getLiveKmlUrl(self,schema,table,useTimestamp=True,REQUEST=None): |
173 if REQUEST is None: | 147 if REQUEST is None: |
174 REQUEST = self.REQUEST | 148 REQUEST = self.REQUEST |
214 fieldMap = self.getFieldNameMap(data['fields']) | 188 fieldMap = self.getFieldNameMap(data['fields']) |
215 | 189 |
216 if (gisIdField is None) and (latField is None or lonField is None): | 190 if (gisIdField is None) and (latField is None or lonField is None): |
217 # no fields given - choose automagically | 191 # no fields given - choose automagically |
218 # gis id in metadata first | 192 # gis id in metadata first |
219 SQL='SELECT "attribute with gis_id" FROM public.metadata WHERE tablename = %s' | 193 #SQL='SELECT "attribute with gis_id" FROM public.metadata WHERE tablename = %s' |
220 res = self.executeSQL(SQL, (table,)) | 194 sql = 'SELECT field_name FROM public.gis_table_meta_rows WHERE table_name = %s and gis_type = %s' |
195 res = self.executeSQL(sql, (table,'gis_id')) | |
221 if len(res['rows']) > 0: | 196 if len(res['rows']) > 0: |
222 gisIdField = res['rows'][0][0] | 197 gisIdField = res['rows'][0][0] |
223 else: | 198 else: |
224 logging.warning("no entry in metadata table for table %s"%table) | 199 logging.warning("no entry in metadata table for table %s"%table) |
225 # try field names | 200 # try field names |